1. 程式人生 > >依賴注入 javax.inject中@Inject、@Named、@Qualifier和@Provider用法

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

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. import com.kaishengit.service.ProjectService;  
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.stereotype.Controller;  
  5. @Controller
      
  6. public class FolderController {  
  7.     private ProjectService projectService;  
  8.     //set  
  9.     @Autowired  
  10.     public void setProjectService(ProjectService projectService) {  
  11.         this.projectService = projectService;  
  12.     }  
  13. }  

 每次都要生成相應的set方法感覺好麻煩,現在如果我們使用javax.inject.jar,只需要在相應類的屬性上面加上@Inject,如下程式碼:

Java程式碼  收藏程式碼
  1. package com.kaishengit.web;  
  2. import com.kaishengit.service.ProjectService;  
  3. import org.springframework.stereotype.Controller;  
  4. import javax.inject.Inject;  
  5. @Controller  
  6. public class FolderController {  
  7.     @Inject  
  8.     private ProjectService projectService;  
  9. }  

@Inject

    @Inject支援建構函式、方法和欄位註解,也可能使用於靜態例項成員。可註解成員可以是任意修飾符(private,package-private,protected,public)。注入順序:建構函式、欄位,然後是方法。父類的欄位和方法注入優先於子類的欄位和方法,同一類中的欄位和方法是沒有順序的。

    @Inject註解的建構函式可以是無參或多個引數的建構函式。@Inject每個類中最多註解一個建構函式。

    在欄位註解:

  • 用@Inject註解
  • 欄位不能是final的
  • 擁有一個合法的名稱

    在方法上註解:

  • 用@Inject註解
  • 不能是抽象方法
  • 不能宣告自身引數型別
  • 可以有返回結果
  • 擁有一個合法的名稱
  • 可以有0個或多個引數

        @Inject MethodModirers ResultType Identifier(FormalParameterList ) Throws MethodBody

    [上述翻譯:inject的doc文件,翻譯不好敬請諒解]

    建構函式註解:

  1. @Inject
  2. public House(Person owner) {  
  3.     System.out.println("---這是房屋建構函式---");  
  4.     this.owner = owner;  
  5. }  
    欄位註解:
  1. @Injectprivate Person owner;  
    方法註解:
  1. @Inject
  2. publicvoid setOwner(Person owner) {  
  3.     this.owner = owner;  
  4. }  
    @Inject註解和Spring的@Autoware註解都是根據型別對其進行自動裝配。

    SpringUtil類:

  1. publicclass SpringUtil {  
  2.     privatestatic ApplicationContext context = null;  
  3.     publicstatic ApplicationContext getApplicationContext() {  
  4.         if (context == null) {  
  5.             context = new ClassPathXmlApplicationContext("spring.xml");  
  6.         }  
  7.         return context;  
  8.     }  
  9.     publicstatic ApplicationContext getApplicationContext(String path) {  
  10.         returnnew ClassPathXmlApplicationContext(path);  
  11.     }  
  12.     publicstatic ApplicationContext getAnnotationConfigApplicationContext(String basePackages) {  
  13.         returnnew AnnotationConfigApplicationContext(basePackages);  
  14.     }  
  15. }  
Person類:
  1. import javax.inject.Named;  
  2. @Named
  3. publicclass Person {  
  4.     private String name;  
  5.     public Person() {  
  6.         System.out.println("---這是人的建構函式---");  
  7.     }  
  8.     public String getName() {  
  9.         return name;  
  10.     }  
  11.     publicvoid setName(String name) {  
  12.         this.name = name;  
  13.     }  
  14. }  
House類:
  1. @Named
  2. publicclass House {  
  3.     @Injectprivate Person owner;  
  4.     public House() {  
  5.         System.out.println("---這是房屋建構函式---");  
  6.     }  
  7.     public Person getOwner() {  
  8.         return owner;  
  9.     }  
  10.     publicvoid setOwner(Person owner) {  
  11.         this.owner = owner;  
  12.     }  
  13. }  
測試類:
  1. publicclass Test {  
  2.     publicstaticvoid 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名稱預設和類名相同。

    例如:

  1. @Namedpublicclass Person  
    該bean的名稱就是person。
  1. @Named("p"publicclass Person  
    如果指定名稱,那麼就是指定的名稱嘍。

@Qualifier

    任何人都可以定義一個新的修飾語,一個qualifier註解應該滿足如下條件:

  • 定義的註解類有@Qualifier,@Retention(RUNTIME)和@Documented。
  • 可以有屬性
  • 可以是公共API的一部分
  • 可以用@Target註解限定使用範圍

    下面是Qualifier的例子:

Genre註解類:

  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.     publicenum User {STUDENT, TEACHER}  
  8. }  
使用者介面:(對個數進行統計)
  1. publicinterface IUserDAO {  
  2.     int count();  
  3. }  
StudentDAO:
  1. @Named
  2. @Genre(user = User.STUDENT)  
  3. publicclass StudentDAO implements IUserDAO{  
  4.     @Override
  5.     publicint count() {  
  6.         System.out.println("----StudentDAO----");  
  7.         return0;  
  8.     }  
  9. }  
TeacherDAO:
  1. @Named
  2. @Genre(user = User.TEACHER)  
  3. publicclass TeacherDAO implements IUserDAO {  
  4.     @Override
  5.     publicint count() {  
  6.         System.out.println("--TeacherDAO--");  
  7.         return0;  
  8.     }  
  9. }  
UserDAOProcessor:
  1. @Named
  2. publicclass UserDAOProcessor {  
  3.     /*對TeacherDAO類的注入,如果對StudentDAO類注入應該是:@Genre(user = User.STUDENT)或@Genre,因為@Genre預設的是STUDENT*/
  4.     @Inject
  5.     private@Genre(user = User.TEACHER) IUserDAO userDAO;   
  6.     publicint count() {  
  7.         return userDAO.count();  
  8.     }  
  9.     public IUserDAO getUserDAO() {  
  10.         return userDAO;  
  11.     }  
  12.     public