HK2是一个轻量级动态依赖注入框架,它是JSR-330的实现。
组件在HK2组件模型中,一个组件的功能是通过服务接口-服务实现的模式声明的。一个HK2服务接口 标识并描述了一个构建模块或者应用程序扩展点。HK2服务实现实现了HK2服务接口。
组件模型(HK2)提供了一个模块系统和组件模型来建立复杂的软件系统。该模块系统负责实例化构成应用程序功能的类。HK2运行时通过创建对象来填充该模块系统。模块系统通过以下方式装配对象:
实例化一个新的对象注入到需要这个对象的对象中。 为这个对象注入所需的配置信息。 使新建的对象可用,这样这些对象就可以注入到其他需要这些对象的对象中。 服务一个HK2服务(服务接口)标识并描述了一个构建模块或者应用程序扩展点。服务是一个普通的Java对象(POJO)具有以下特点:
该对象(类)实现了一个接口 对象(类)应该在JAR的META-INF/services文件中声明 作用范围@Singleton
生命周期组件可以在初始化和销毁事件发生过程中,添加切面逻辑,实现接口:org.jvnet.hk2.component.PostConstruct 和 org.jvnet.hk2.component.PreDestroy。
实现接口还是使用注解,可以根据性能决定。
PostConstruct.postConstruct() :这个方法在组件初始化并且组件的依赖被注入后调用。 PreDestroy.preDestroy() :这个方法在组件从系统移除前调用。
@Service(name="")public class MyContainer implements Container, PostConstruct, PreDestroy { @Inject Logger logger; ... public void postConstruct() { logger.info("Starting up."); } public void preDestroy() { logger.info("Shutting down."); }} 定义服务 默认实现 //默认只有一种实现的情况,接口定义:@Contractpublic interface Foo {}//具体业务在实现类中@Servicepublic class FooImpl implements Foo {} 服务命名 //为了区分相同的接口的不同实现,你可以给你的服务命名。如下例子:@Contractpublic interface Book {}@Service @Namedpublic class Moby implements Book {}@Service @Namedpublic class ParadiseLost implements Book {} 限定服务 //服务也可以被注解限定调用。这个注解需要标注@Qualifier注解,看例子:@Contractpublic interface Color {}@Service @Bluepublic class BlueColor implements Color {}@Service @Redpublic class RedColor implements Color {}//Blue注解的实现@Qualifier@Retention(RUNTIME)@Target( { TYPE, METHOD, FIELD, PARAMETER })public @interface Blue {} 注入服务 基础注入 //作为成员变量注入:@InjectConfigService config;//setter上注入@Injectpublic void set(ConfigService config) {...}//也可通过构造函数注入@Servicepublic class FooImpl implements Foo { private final Book book; @Inject public FooImpl(Book book) { // constructor injected! this.book = book; }} 名称注入(Injection by name) //需要给服务命名,然后通过名称才能注入,看例子:@Servicepublic class FooImpl implements Foo { @Inject @Named("Moby") private Book mobyDick; @Inject @Named("ParadiseLost") private Book paradiseLost;} 限定注入(Injection by qualifier) //限定服务,按照以下方式注入,看例子:@Servicepublic class ColorMixer { private Color red; private Color blue; @Inject private void addPrimaries(@Red Color red, @Blue Color blue) { this.red = red; this.blue = blue; }} Provider注入很多情况下,注入一个服务的Provider要比注入服务本身要好,因为系统可能延时创建服务,直到Provider的get方法被调用。
@Servicepublic class ColorMixer { @Inject @Red private Provider<Color> redProvider; @Inject @Blue private Provider<Color> blueProvider;}//服务中可以在需要时再调用@Servicepublic class ColorMixer { ... public Color makePurple() { return mix(redProvider.get(), blueProvider.get()); }} IterableProvider注入通常情况下,一个contract会有多个实现,如果要访问所有的实现,就需要使用IterableProvider。
@Servicepublic class Library { @Inject private IterableProvider<Book> allBooks; public LinkedList<Book> getAllBooks() { LinkedList<Book> retVal = new LinkedList<Book>(); for (Book book : allBooks) { retVal.add(book); } return retVal; }}//另外一个特性,我们可以使用named获取一个特定的实现。@Servicepublic class Library { @Inject private IterableProvider<Book> allBooks; public Book findBook(String name) { return allBooks.named(name).get(); }} Iterable注入Iterable can be used as an injection point rather than IterableProvider.
@Servicepublic class Library { @Inject private Iterable<Book> allBooks; public LinkedList<Book> getAllBooks() { LinkedList<Book> retVal = new LinkedList<Book>(); for (Book book : allBooks) { retVal.add(book); } return retVal; }} 总结如果对底层实现感兴趣,不如去看看这个kunJ,当然,给个star也是极好的。