依赖注入 javax.inject中@Inject、@Named、@Qualifier和@Provider用法

这个是 Java EE 6 规范 JSR 330 -- Dependency Injection for Java 中的东西,也就是 Java EE 的依赖注入。

根据 API document 上的说明,被 @Inject 标注的构造、成员字段和方法是可注入的。

其包可以在 jcp.org 上找到,并可以在这里下载:

https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_JCP-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=dependency_injection-1.0-final-oth-JSpec@CDS-CDS_JCP



  • Spring自带的@Autowired的缺省情况等价于JSR-330的@Inject注解;
  • Spring自带的@Qualifier的缺省的根据Bean名字注入情况等价于JSR-330的@Named注解;
  • Spring自带的@Qualifier的扩展@Qualifier限定描述符注解情况等价于JSR-330的@Qualifier注解。

    用过spring框架的我们都知道,每当生成依赖注入的时候,我们都必须生成相应类的set方法,而且要在set方法上面写上@Autowired,才能实现依赖注入,如下:

    Java代码   收藏代码
    1. package com.kaishengit.web;  
    2.   
    3. import com.kaishengit.service.ProjectService;  
    4. import org.springframework.beans.factory.annotation.Autowired;  
    5. import org.springframework.stereotype.Controller;  
    6.   
    7. @Controller  
    8. public class FolderController {  
    9.     private ProjectService projectService;  
    10.   
    11.     //set  
    12.     @Autowired  
    13.     public void setProjectService(ProjectService projectService) {  
    14.         this.projectService = projectService;  
    15.     }  
    16. }  

     每次都要生成相应的set方法感觉好麻烦,现在如果我们使用javax.inject.jar,只需要在相应类的属性上面加上@Inject,如下代码:

    Java代码   收藏代码
    1. package com.kaishengit.web;  
    2.   
    3. import com.kaishengit.service.ProjectService;  
    4. import org.springframework.stereotype.Controller;  
    5.   
    6. import javax.inject.Inject;  
    7.   
    8. @Controller  
    9. public class FolderController {  
    10.     @Inject  
    11.     private ProjectService projectService;  
    12.   
    13.   
    14. }  

     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
    1. @Inject  
    2. public House(Person owner) {  
    3.     System.out.println("---这是房屋构造函数---");  
    4.     this.owner = owner;  
    5. }  
        字段注解:

    [java]  view plain copy
    1. @Inject private Person owner;  
        方法注解:

    [java]  view plain copy
    1. @Inject  
    2. public void setOwner(Person owner) {  
    3.     this.owner = owner;  
    4. }  
        @Inject注解和Spring的@Autoware注解都是根据类型对其进行自动装配。

        SpringUtil类:

    [java]  view plain copy
    1. public class SpringUtil {  
    2.     private static ApplicationContext context = null;  
    3.     public static ApplicationContext getApplicationContext() {  
    4.         if (context == null) {  
    5.             context = new ClassPathXmlApplicationContext("spring.xml");  
    6.         }  
    7.         return context;  
    8.     }  
    9.   
    10.     public static ApplicationContext getApplicationContext(String path) {  
    11.         return new ClassPathXmlApplicationContext(path);  
    12.     }  
    13.   
    14.     public static ApplicationContext getAnnotationConfigApplicationContext(String basePackages) {  
    15.         return new AnnotationConfigApplicationContext(basePackages);  
    16.     }  
    17. }  
    Person类:

    [java]  view plain copy
    1. import javax.inject.Named;  
    2.   
    3. @Named  
    4. public class Person {  
    5.     private String name;  
    6.   
    7.     public Person() {  
    8.         System.out.println("---这是人的构造函数---");  
    9.     }  
    10.   
    11.     public String getName() {  
    12.         return name;  
    13.     }  
    14.   
    15.     public void setName(String name) {  
    16.         this.name = name;  
    17.     }  
    18. }  
    House类:

    [java]  view plain copy
    1. @Named  
    2. public class House {  
    3.     @Inject private Person owner;  
    4.     public House() {  
    5.         System.out.println("---这是房屋构造函数---");  
    6.     }  
    7.   
    8.     public Person getOwner() {  
    9.         return owner;  
    10.     }  
    11.   
    12.     public void setOwner(Person owner) {  
    13.         this.owner = owner;  
    14.     }  
    15. }  
    测试类:

    [java]  view plain copy
    1. public class Test {  
    2.     public static void main(String[] args) {  
    3.         ApplicationContext context = SpringUtil.getApplicationContext(  
    4.                 "test/spring/inject/bean-inject.xml");  
    5.         House house = (House)context.getBean("house");  
    6.         Person p = house.getOwner();  
    7.         p.setName("张三");  
    8.         System.out.println(house.getOwner().getName());  
    9.     }  
    10. }  
    输出结果:

    ---这是房屋构造函数---
    ---这是人的构造函数---
    张三

        上述例子在Spring3.1下测试成功,在Spring3.1下,每个构造函数只初始化一次及默认的单例形式,个人感觉如果脱离Spring环境应该每次用都会实例化新的对象,当然根据实现的jar包不同而不同,要不javax.inject下的@Singleton注解就没有什么用途了。

    @Named

        @Named和Spring的@Component功能相同。@Named可以有值,如果没有值生成的Bean名称默认和类名相同。

        例如:

    [java]  view plain copy
    1. @Named public class Person  
        该bean的名称就是person。

    [java]  view plain copy
    1. @Named("p"public class Person  
        如果指定名称,那么就是指定的名称喽。

    @Qualifier

        任何人都可以定义一个新的修饰语,一个qualifier注解应该满足如下条件:

    • 定义的注解类有@Qualifier,@Retention(RUNTIME)和@Documented。
    • 可以有属性
    • 可以是公共API的一部分
    • 可以用@Target注解限定使用范围

        下面是Qualifier的例子:

    Genre注解类:

    [java]  view plain copy
    1. @Documented  
    2. @Retention(RetentionPolicy.RUNTIME)  
    3. @Qualifier  
    4. @Target(value = {ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})  
    5. public @interface Genre {  
    6.     User user() default User.STUDENT;  
    7.     public enum User {STUDENT, TEACHER}  
    8. }  
    用户接口:(对个数进行统计)

    [java]  view plain copy
    1. public interface IUserDAO {  
    2.     int count();  
    3. }  
    StudentDAO:

    [java]  view plain copy
    1. @Named  
    2. @Genre(user = User.STUDENT)  
    3. public class StudentDAO implements IUserDAO{  
    4.     @Override  
    5.     public int count() {  
    6.         System.out.println("----StudentDAO----");  
    7.         return 0;  
    8.     }  
    9.   
    10. }  
    TeacherDAO:

    [java]  view plain copy
    1. @Named  
    2. @Genre(user = User.TEACHER)  
    3. public class TeacherDAO implements IUserDAO {  
    4.   
    5.     @Override  
    6.     public int count() {  
    7.         System.out.println("--TeacherDAO--");  
    8.         return 0;  
    9.     }  
    10. }  
    UserDAOProcessor:

    [java]  view plain copy
    1. @Named  
    2. public class UserDAOProcessor {  
    3.     /*对TeacherDAO类的注入,如果对StudentDAO类注入应该是:@Genre(user = User.STUDENT)或@Genre,因为@Genre默认的是STUDENT*/  
    4.     @Inject  
    5.     private @Genre(user = User.TEACHER) IUserDAO userDAO;   
    6.   
    7.     public int count() {  
    8.         return userDAO.count();  
    9.     }  
    10.   
    11.     public IUserDAO getUserDAO() {  
    12.         return userDAO;  
    13.     }  
    14.   
    15.     public void setUserDAO(IUserDAO userDAO) {  
    16.         this.userDAO = userDAO;  
    17.     }  
    18. }  


    测试类:

    [java]  view plain copy
    1. public class Test {  
    2.     public static void main(String[] args) {  
    3.         ApplicationContext context = SpringUtil.getApplicationContext(  
    4.                 "test/spring/inject/bean-inject.xml");  
    5.         UserDAOProcessor processor = (UserDAOProcessor)context.getBean("userDAOProcessor");  
    6.         System.out.println(processor.count());  
    7.     }  
    8. }  
    输出结果:

    --TeacherDAO--
    0

        个人对@Qualifier的理解:

    1. 和Spring的@Qualifier大致相同
    2. 单独用@Inject无法满足对接口的注入,无法找到哪个具体类,所以用@Qualifier来确定注入的具体类
    3. 用到@Qualifier的注解中可以有值、无值和用枚举类型

    @Singleton

        使用该注解标记该类只创建一次,不能被继承。一般在类上用该注解。

  • Spring自带的@Autowired的缺省情况等价于JSR-330的@Inject注解;
  • Spring自带的@Qualifier的缺省的根据Bean名字注入情况等价于JSR-330的@Named注解;
  • Spring自带的@Qualifier的扩展@Qualifier限定描述符注解情况等价于JSR-330的@Qualifier注解。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值