Spring自带的@Autowired的缺省情况等价于JSR-330的@Inject注解; Spring自带的@Qualifier的缺省的根据Bean名字注入情况等价于JSR-330的@Named注解; Spring自带的@Qualifier的扩展@Qualifier限定描述符注解情况等价于JSR-330的@Qualifier注解。
用过spring框架的我们都知道,每当生成依赖注入的时候,我们都必须生成相应类的set方法,而且要在set方法上面写上@Autowired,才能实现依赖注入,如下:
Java代码 package com.kaishengit.web; 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) { 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下载地址:https://code.google.com/p/dependency-shot/downloads/detail?name=javax.inject.jar&can=2&q=
@Inject
@Inject支持构造函数、方法和字段注解,也可能使用于静态实例成员。可注解成员可以是任意修饰符(private,package-private,protected,public)。注入顺序:构造函数、字段,然后是方法。父类的字段和方法注入优先于子类的字段和方法,同一类中的字段和方法是没有顺序的。
@Inject注解的构造函数可以是无参或多个参数的构造函数。@Inject每个类中最多注解一个构造函数。
在字段注解:
用@Inject注解字段不能是final的拥有一个合法的名称在方法上注解:
用@Inject注解不能是抽象方法不能声明自身参数类型可以有返回结果拥有一个合法的名称可以有0个或多个参数@Inject MethodModirers ResultType Identifier(FormalParameterList ) Throws MethodBody
[上述翻译:inject的doc文档,翻译不好敬请谅解]
构造函数注解:
[java] view plain copy @Inject public House(Person owner) { System.out.println("---这是房屋构造函数---"); this.owner = owner; } 字段注解:
[java] view plain copy @Inject private Person owner; 方法注解:
[java] view plain copy @Inject public void setOwner(Person owner) { this.owner = owner; } @Inject注解和Spring的@Autoware注解都是根据类型对其进行自动装配。
SpringUtil类:
[java] view plain copy 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类:
[java] view plain copy 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类:
[java] view plain copy @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; } } 测试类:
[java] view plain copy 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
@Named和Spring的@Component功能相同。@Named可以有值,如果没有值生成的Bean名称默认和类名相同。
例如:
[java] view plain copy @Named public class Person 该bean的名称就是person。
[java] view plain copy @Named("p") public class Person 如果指定名称,那么就是指定的名称喽。
@Qualifier
任何人都可以定义一个新的修饰语,一个qualifier注解应该满足如下条件:
定义的注解类有@Qualifier,@Retention(RUNTIME)和@Documented。可以有属性可以是公共API的一部分可以用@Target注解限定使用范围下面是Qualifier的例子:
Genre注解类:
[java] view plain copy @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} } 用户接口:(对个数进行统计)
[java] view plain copy public interface IUserDAO { int count(); } StudentDAO:
[java] view plain copy @Named @Genre(user = User.STUDENT) public class StudentDAO implements IUserDAO{ @Override public int count() { System.out.println("----StudentDAO----"); return 0; } } TeacherDAO:
[java] view plain copy @Named @Genre(user = User.TEACHER) public class TeacherDAO implements IUserDAO { @Override public int count() { System.out.println("--TeacherDAO--"); return 0; } } UserDAOProcessor:
[java] view plain copy @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; } }
测试类:
[java] view plain copy public class Test { public static void main(String[] args) { ApplicationContext context = SpringUtil.getApplicationContext( "test/spring/inject/bean-inject.xml"); UserDAOProcessor processor = (UserDAOProcessor)context.getBean("userDAOProcessor"); System.out.println(processor.count()); } } 输出结果:
--TeacherDAO-- 0
个人对@Qualifier的理解:
和Spring的@Qualifier大致相同单独用@Inject无法满足对接口的注入,无法找到哪个具体类,所以用@Qualifier来确定注入的具体类用到@Qualifier的注解中可以有值、无值和用枚举类型@Singleton
使用该注解标记该类只创建一次,不能被继承。一般在类上用该注解。
Spring自带的@Autowired的缺省情况等价于JSR-330的@Inject注解; Spring自带的@Qualifier的缺省的根据Bean名字注入情况等价于JSR-330的@Named注解; Spring自带的@Qualifier的扩展@Qualifier限定描述符注解情况等价于JSR-330的@Qualifier注解。