這個是 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代碼
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 plaincopy@Inject public House(Person owner) { System.out.println("---這是房屋構造函數---"); this.owner = owner; } 字段注解:[java] view plaincopy@Inject private Person owner; 方法注解:[java] view plaincopy@Inject public void setOwner(Person owner) { this.owner = owner; } @Inject注解和Spring的@Autoware注解都是根據類型對其進行自動裝配。SpringUtil類:
[java] view plaincopypublic 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 plaincopyimport 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 plaincopy@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 plaincopypublic 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 plaincopy@Named public class Person 該bean的名稱就是person。[java] view plaincopy@Named("p") public class Person 如果指定名稱,那么就是指定的名稱嘍。@Qualifier
任何人都可以定義一個新的修飾語,一個qualifier注解應該滿足如下條件:
定義的注解類有@Qualifier,@Retention(RUNTIME)和@Documented。可以有屬性可以是公共API的一部分可以用@Target注解限定使用范圍下面是Qualifier的例子:
Genre注解類:
[java] view plaincopy@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 plaincopypublic interface IUserDAO { int count(); } StudentDAO:[java] view plaincopy@Named @Genre(user = User.STUDENT) public class StudentDAO implements IUserDAO{ @Override public int count() { System.out.println("----StudentDAO----"); return 0; } } TeacherDAO:[java] view plaincopy@Named @Genre(user = User.TEACHER) public class TeacherDAO implements IUserDAO { @Override public int count() { System.out.println("--TeacherDAO--"); return 0; } } UserDAOProcessor:[java] view plaincopy@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 plaincopypublic 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注解。新聞熱點
疑難解答