这个是 Java EE 6 规范 JSR 330 – Dependency Injection for Java 中的东西,也就是 Java EE 的依赖注入。
根据 API document 上的说明,被 @Inject 标注的构造、成员字段和方法是可注入的。
用过Spring框架的我们都知道,每当生成依赖注入的时候,我们都必须生成相应类的set方法,而且要在set方法上面写上@Autowired,才能实现依赖注入,如下:
import com.kaishengit.service.ProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class FolderController {
private ProjectService projectService;
//set
@Autowired
public void setProjectService(ProjectService projectService) { @Component
this.projectService = projectService;
}
}
这样每次都要生成相应的set方法非常麻烦,现在如果我们使用javax.inject.jar
,只需要在相应类的属性上面加上@Inject
,如下代码:
Java代码
package com.kaishengit.web;
import com.kaishengit.service.ProjectService;
import org.springframework.stereotype.Controller;
import javax.inject.Inject;
@Controller
public class FolderController {
@Inject
private ProjectService projectService;
}
javax.inject.jar
下载地址:点我
@Inject支持构造函数、方法和字段注解,也可能使用于静态实例成员。可注解成员可以是任意修饰符(private,package-private,protected,public)。
注入顺序:构造函数、字段,然后是方法。父类的字段和方法注入优先于子类的字段和方法,同一类中的字段和方法是没有顺序的。
@Inject注解的构造函数可以是无参或多个参数的构造函数。@Inject每个类中最多注解一个构造函数。
1. 在字段注解:
用@Inject注解
● 字段不能是final的
● 拥有一个合法的名称
2. 在方法上注解:
● 用@Inject注解
● 不能是抽象方法
● 不能声明自身参数类型
● 可以有返回结果
● 拥有一个合法的名称
● 可以有0个或多个参数
构造函数注解:
@Inject
public House(Person owner) {
System.out.println("---这是房屋构造函数---");
this.owner = owner;
}
字段注解:
@Inject private Person owner;
方法注解:
@Inject
public void setOwner(Person owner) {
this.owner = owner;
}
@Inject注解和Spring的@Autoware注解都是根据类型对其进行自动装配。
测试
SpringUtil类:
public class SpringUtil {
private static ApplicationContext context = null;
public static ApplicationContext getApplicationContext() {
if (context == null) {
context = new ClassPathXmlApplicationContext("spring.xml");
}
return context;
}
public static ApplicationContext getApplicationContext(String path) {
return new ClassPathXmlApplicationContext(path);
}
public static ApplicationContext getAnnotationConfigApplicationContext(String basePackages) {
return new AnnotationConfigApplicationContext(basePackages);
}
}
Person类:
import javax.inject.Named;
@Named
public class Person {
private String name;
public Person() {
System.out.println("---这是人的构造函数---");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
House类:
@Named
public class House {
@Inject private Person owner;
public House() {
System.out.println("---这是房屋构造函数---");
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
}
测试类:
public class Test {
public static void main(String[] args) {
ApplicationContext context = SpringUtil.getApplicationContext(
"test/spring/inject/bean-inject.xml");
House house = (House)context.getBean("house");
Person p = house.getOwner();
p.setName("张三");
System.out.println(house.getOwner().getName());
}
}
输出结果:
—这是房屋构造函数—
—这是人的构造函数—
张三
上述例子在Spring3.1下测试成功,在Spring3.1下,每个构造函数只初始化一次及默认的单例形式,感觉如果脱离Spring环境应该每次用都会实例化新的对象,当然根据实现的jar包不同而不同,要不javax.inject下的@Singleton注解就没有什么用途了。
@Named
和Spring的@Component
功能相同。@Named可以有值,如果没有值生成的Bean名称默认和类名相同。
例如:
1. @Named public class Person
该bean的名称就是person。
2. @Named(“p”) public class Person
如果指定名称,那么就是指定的名称喽。
任何人都可以定义一个新的修饰语,一个qualifier注解应该满足如下条件:
● 定义的注解类有@Qualifier,@Retention(RUNTIME)和@Documented。
● 可以有属性
● 可以是公共API的一部分
● 可以用@Target注解限定使用范围
下面是Qualifier的例子:
Genre注解类:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Target(value = {ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface Genre {
User user() default User.STUDENT;
public enum User {STUDENT, TEACHER}
}
用户接口:(对个数进行统计)
public interface IUserDAO {
int count();
}
StudentDAO:
@Named
@Genre(user = User.STUDENT)
public class StudentDAO implements IUserDAO{
@Override
public int count() {
System.out.println("----StudentDAO----");
return 0;
}
}
TeacherDAO:
@Named
@Genre(user = User.TEACHER)
public class TeacherDAO implements IUserDAO {
@Override
public int count() {
System.out.println("--TeacherDAO--");
return 0;
}
}
UserDAOProcessor:
@Named
public class UserDAOProcessor {
/*对TeacherDAO类的注入,如果对StudentDAO类注入应该是:@Genre(user = User.STUDENT)或@Genre,因为@Genre默认的是STUDENT*/
@Inject
private @Genre(user = User.TEACHER) IUserDAO userDAO;
public int count() {
return userDAO.count();
}
public IUserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
}
测试类:
public class Test {
public static void main(String[] args) {
ApplicationContext context = SpringUtil.getApplicationContext( T*/
"test/spring/inject/bean-inject.xml");
UserDAOProcessor processor = (UserDAOProcessor)context.getBean("userDAOProcessor");
System.out.println(processor.count());
}
}
输出结果:
–TeacherDAO–
0
个人对@Qualifier
的理解:
1. 和Spring的@Qualifier大致相同
2. 单独用@Inject无法满足对接口的注入,无法找到哪个具体类,所以用@Qualifier来确定注入的具体类
3. 用到@Qualifier的注解中可以有值、无值和用枚举类型
使用该注解标记该类只创建一次,不能被继承。一般在类上用该注解。