HK2使用详解

摘要:
组件的功能是通过服务接口服务实现模式声明的。HK2服务接口识别并描述构建模块或应用程序扩展点。服务HK2服务(服务接口)标识和描述构建模块或应用程序扩展点。这个对象(类)实现了一个接口对象。在初始化和销毁事件期间,它应该在JAR的META-INF/services文件中声明scope@Singleton生命周期组件。

HK2介绍

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.");
    }
}

定义服务

#### 默认实现 ```java //默认只有一种实现的情况,接口定义: @Contract public interface Foo { } //具体业务在实现类中 @Service public class FooImpl implements Foo { } ```

服务命名

//为了区分相同的接口的不同实现,你可以给你的服务命名。如下例子:
@Contract
public interface Book {
}

@Service @Named
public class Moby implements Book {
}

@Service @Named
public class ParadiseLost implements Book {
}

限定服务

//服务也可以被注解限定调用。这个注解需要标注@Qualifier注解,看例子:
@Contract
public interface Color {
}

@Service @Blue
public class BlueColor implements Color {
}

@Service @Red
public class RedColor implements Color {
}
//Blue注解的实现
@Qualifier
@Retention(RUNTIME)
@Target( { TYPE, METHOD, FIELD, PARAMETER })
public @interface Blue {
}

注入服务

#### 基础注入 ```java //作为成员变量注入: @Inject ConfigService config; //setter上注入 @Inject public void set(ConfigService config) {...} //也可通过构造函数注入 @Service public class FooImpl implements Foo { private final Book book;

@Inject
public FooImpl(Book book) {
// constructor injected!
this.book = book;
}
}


#### 名称注入(Injection by name)
```java
//需要给服务命名,然后通过名称才能注入,看例子:
@Service
public class FooImpl implements Foo {
  @Inject @Named("Moby")
  private Book mobyDick;

  @Inject @Named("ParadiseLost")
  private Book paradiseLost;
}

限定注入(Injection by qualifier)

//限定服务,按照以下方式注入,看例子:
@Service
public 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方法被调用。

@Service
public class ColorMixer {
    @Inject @Red
    private Provider<Color> redProvider;

    @Inject @Blue
    private Provider<Color> blueProvider;
}
//服务中可以在需要时再调用
@Service
public class ColorMixer {
    ...

    public Color makePurple() {
      return mix(redProvider.get(), blueProvider.get());
    }
}

IterableProvider注入

通常情况下,一个contract会有多个实现,如果要访问所有的实现,就需要使用IterableProvider。

@Service
public 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获取一个特定的实现。
@Service
public 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.

@Service
public 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也是极好的。

免责声明:文章转载自《HK2使用详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇V-rep学习笔记:机器人模型创建1—模型简化Servlet(三)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Delphi之TComponent类

TComponent类 TComponent类直接由TPersistent派生。TComponent的独特特征是它的属性能够在设计期间通过ObjectInspector来控制,能够拥有其他组件。非可视组件也是从TComponent派生的,因此它们也继承了在设计期间可以被控制的能力。TComponent派生的非可视对象的典型例子是TTimer组件。TTim...

[置顶] Windows显示驱动(WDDM)编程初步(2)

欢迎转载【作者:张佩】【原文:http://www.yiiyee.cn/Blog/wddm2/】 第二部分专门只讲VIDPN。这是后面内容的基础。WDDM框架用VIDPN这个概念,来描述它所要处理的显示关系。 VIDPN VIDPN的全称是Video Present Network,这个因为词组不太好翻译(直译可以是:视频提交网络,但颇为难听),所以一般都...

Pandorabox(Openwrt) 双宽带(WAN) 叠加网络实战

准备 一台已经刷好Pandorabox(Openwrt)的路由器、两条宽带 实战环境 固件:PandoraBox R8.1.12 By Lean 硬件:K2P A1版 过程 配置VLAN 为了将一个LAN口映射为WAN口,选择网络-交换机,添加一个VLAN3,比如我希望将LAN1口配置为WAN口,在VLAN1中把LAN1配置为关,VLAN3中除LAN1...

说说接口封装

今天给同事封装了一个接口,说起接口封装的事情,其实其实很有的聊。很多时候,说一个服务好,一个服务烂,实际上都是在吐槽服务队外暴露的接口好坏。不管什么语言,封装接口,抽象起来,就是由一个函数名,若干个参数,若干个返回值组成的。封装的好坏,就在这几个上面。 函数名 首先是函数名。函数名的好坏很明显,我的观点,是否简单,不重复。比如在一个User类中你封装一个...

python Zope.interface安装使用

一、接口简述 在我们所熟知的面向对象编程语言中,大多提供了接口(interface)的概念。接口在编程语言中指的是一个抽象类型,是抽象方法的集合;它的特点如下: 1、类通过继承接口的方式,来继承接口的抽象方法; 2、接口并不是类(虽然编写类和方法的方式很相似); 3、类描述对象的属性和方法(实现接口的类,必须实现接口内所描述的所有方法,否则必须声明为抽象类...

JAVA序列化:implements Serializable

什么是序列化: 序列化的过程,就是一个“freeze”的过程,它将一个对象freeze住,然后进行存储,等到再次需要的时候,再将这个对象de-freeze就可以立即使用。 什么情况下需要序列化: 原文:https://blog.csdn.net/dinghqalex/article/details/46009911          1.     当你想把...