如何使HK2像Guice一样注入未明确配置的类?

时间:2017-09-25 18:08:17

标签: java dependency-injection guice hk2

我有一个使用Jersey 2.25的项目(HK2 2.5-b30)。最初,我使用的是HK2-Guice Bridge。但是,在某些情况下,这似乎意外地失败了(特别是,当Guice正在执行注入时,使用Guice中配置的自定义注释对字符串进行注释的情况将正常工作,但在HK2执行注入时会无声地失败)。因为同一个物体的注入方式可能会有所不同,所以我很害怕同时使用它们。

我现在正在改变一切使用HK2,但遗憾的是,在某些Guice成功的情况下,HK2似乎失败了。特别是,似乎HK2不喜欢注入没有明确配置类型的地方。 Guice很高兴只是创建这些类的新实例并递归注入,但HK2并没有那么多。例如,

1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=TimeRangeRequestValidator,parent=GetWatchlistEventsImpl,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1218743359)

如您所见,错误消息根本不是很有帮助。它应该能够创建一个TimeRangeRequestValidator,它引用了一些其他对象,Guice能够毫无问题地创建所有这些对象。在HK2和Guice之间是否有一些不同的行为列表,所以我可以找出为什么这不起作用?

请注意TimeRangeRequestValidator是一个用@Singleton注释的类(不是接口),它有一个默认的公共构造函数和一个用Inject注释的字段。 Guice在实例化时没有任何问题。

2 个答案:

答案 0 :(得分:2)

你也可以使用贪婪的JustInTimeResolver。我在下面写了一篇:

@Singleton
@Visibility(DescriptorVisibility.LOCAL)
public class GreedyResolver implements JustInTimeInjectionResolver {
    private final ServiceLocator locator;

    @Inject
    private GreedyResolver(ServiceLocator locator) {
        this.locator = locator;
    }

    @Override
    public boolean justInTimeResolution(Injectee failedInjectionPoint) {
        Type type = failedInjectionPoint.getRequiredType();
        if (type == null) return false;

        Class<?> clazzToAdd = null;
        if (type instanceof Class) {
            clazzToAdd = (Class<?>) type;
        }
        else if (type instanceof ParameterizedType) {
            Type rawType = ((ParameterizedType) type).getRawType();
            if (rawType instanceof Class) {
                clazzToAdd = (Class<?>) rawType;
            }
        }

        if (clazzToAdd == null) return false;
        if (clazzToAdd.isInterface()) return false;

        ServiceLocatorUtilities.addClasses(locator, clazzToAdd);
        return true;
    }

}

使用上面的解析器时应该小心,因为它会在ServiceLocator中添加您可能没想到的内容。注入像Strings或其他类似的东西也可能不会很好。不过,可能适用于您的用例。

如果您的注射点正在注入接口,则无效!

答案 1 :(得分:1)

a few extra steps you need个配置HK2来自动填充您的服务:

  1. 确保您已使用@Contract注释了您的界面,并使用@Service
  2. 注释了您的实施
  3. 您需要在构建期间运行HK2 Metadata Generator。这将生成HK2在运行时需要的服务文件,以确定哪些类实现了哪些合同接口。
  4. 使用ServiceLocatorUtilities.createAndPopulateServiceLocator()检索ServiceLocator个实例。
  5. 请注意,具体或如何适用于您取决于您​​使用的框架(如球衣)。请参阅Using HK2 with Jersey