依赖注入:Dependency Injection

一 ,Java EE 实现依赖注入

java EE 为了摆脱XML配置,java EE新增了几个注解来执行注入
1,@Resource(),用于注入数据源、java消息服务(JMS)、URL、邮件与环境变量
2,@EJB,用于注入EJB
3,@WebServiceRef 用于注入Web Service
4,@Inject 注解DI是类型安全的,因为它会根据对象引用类型注入依赖。

import javax.inject.Inject;

class UserService7 {

	@Inject
	private UserDataRepository udr;

	public void persistUser(User user) {
		udr.save(user);
	}
}
public class UserDataRepositoryImpl implements UserDataRepository {
	@Override
	public void save(User user) {
		// Persistence Code Here
	}
}
public interface UserDataRepository {
	public void save(User user);
}

CDI容器构建了一个UserDataRepositoryImpl实例作为容器管理的bean,如果类型为UserDataRepository的字段上发现了@Inject注解,那么就将其注入进去。

你可以将容器管理的Bean注入构造方法、方法与字段中,无论其访问修饰符是什么,不过字段不可以是final,方法也不能去抽象的

当UserDataRepository接口有多个实现的情况,假设这个接口有两个实现:一个用于MogoDB ,一个用于MySQL。你需要创建两个限定符进行注解,同时再注入UserDataRepository的类中要有一个字段使用相同的限定符进行注解,如下

@Inject @Mongo
	private UserDataRepository udr;

二 @Named 注解

它取代了字符串限定符
用于消除歧义的@Named注解,下面是UserDataRposiory的Mongo实现

import javax.inject.Inject;
import javax.inject.Named;

class UserService8 {

	@Inject
	@Named("UserDataRepositoryMongo")
	private UserDataRepository udr;

	public void persistUser(User user) {
		udr.save(user);
	}
}

@Named注解需要一个显式声明的Mongo实现。再下面代码中,UserDataRepository接口的Mongo实现也使用了一个注解,并且该注解与上面代码用于消除被注入实现的歧义而使用的字符串名字相同

具体实现需要@Named注解

import javax.inject.Named;

@Named("UserDataRepositoryMongo")
public class UserDataRepositoryMongo implements UserDataRepository {

	@Override
	public void save(User user) {
		// Persistence Code Here
	}
}

三 上下文与依赖注入(CDI)

CDI通过实例化并注入对象实现了与任何普通java对象(POJO)的协同工作。如下类型的对象是可以注入的:
1,POJO
2,企业资源,如数据源与队列
3,远程EJB引用
4,会话Bean
5,EntityManager对象
6,Web Services引用
7,生产者字段与生产者方法返回的对象

CDI容器是一个面向POJO的轻量级、强大、但功能精简的容器,CDI注解可以作为与EJB容器交互的网关与标准接口。比如说,@Inject注解可以用于POJO或EJB上,通过正确的容器进行处理来注入二者的任意组合

四 ,CDI Bean

容器管理的Bean只不过是一个遵循某些简单规则的POJO

1,必须有一个无参构造方法,否则构造方法就要声明一个@inject注解
2,必须是顶层的具体类,不能是个非静态的内部类
3,不能定义为EJB
4,如果Bean被其它的java EE技术 定义为一个管理Bean,那么它也会由容器所管理

EJB与CDI容器的上下文是不同的,每个CDI Bean的生命周期都会绑定到一个上下文作用域上,CDI提供了4种不同的作用域
1,@RequestScoped 持续时间为用户的HTTP请求时间
2, @SessionScoped 持续时间为用户的HTTP会话时间
3, @ApplicationScoped 状态会在应用运行期间被所有用户共享
4, @ConversationScoped 由开发者控制作用域的持续时间

五,限定符

创建一个名为Mongo的限定类符,可以通过它对字段进行注解。如果要在METHOD、PARAMETER或是类/接口(TYPE)上使用该注解,可将其添加到@Target注解上

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({FIELD})
public @interface Mongo {}