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

问题描述:

我有一个项目使用Jersey 2.25(与HK2 2.5-b30)。最初,我使用的是HK2-Guice Bridge。但是,对于某些情况,这似乎意外失败(尤其是在Guice配置的自定义注释中注释了字符串的情况下,Guice执行注入时会正常工作,但在HK2执行时会默默失败)。因为同一个对象根据注入方式的不同可能会有所不同,所以我很害怕将它们结合使用。如何让HK2像Guice一样注入未明确配置的类?

我现在正在切换所有使用HK2,但遗憾的是,似乎HK2在某些情况下失败,Guice会成功。特别是,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没有任何问题实例化。

您还可以使用贪婪的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; 
    } 

} 

使用上述解析器的时候,因为它会添加东西到你的服务定位器,你可能没有指望你应该小心。它也可能不适合注入像Strings或其他类型的东西。不过,可能适合你的用例。

如果您的注射点正在注入一个接口,将无法正常工作!

+0

是的;这看起来像我需要的东西。我会添加一些检查,以确保我实际上正在注入我想要注入的东西。我认为这正是吉斯桥所使用的,但至少这样做明确地提供了更多的可见性和控制力。 –

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

  1. 确保您已标注了@Contract的接口和你的实现与@Service
  2. 您需要在构建过程中运行HK2 Metadata Generator 。这会生成HK2在运行时需要的服务文件,以确定哪些类可以实现哪些合约接口。
  3. 使用ServiceLocatorUtilities.createAndPopulateServiceLocator()检索ServiceLocator实例。

请注意,具体细节或如何为您工作取决于您正在使用什么样的框架(如球衣)。见Using HK2 with Jersey