Autowired顧名思義,表示自動注入,以下是Autowired註解的源代碼:java
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/** * Declares whether the annotated dependency is required. * <p>Defaults to {@code true}. */
boolean required() default true;
}
複製代碼
從Autowired的實現能夠看到,Autowired能夠用於類的構造方法,類的字段,類的方法以及註解類型上,可是Autowired不能用於類上面。app
關於Autowired註解,有以下問題須要解決:ide
1. Autowired做用在不一樣的範圍上(構造方法,字段、方法)上,它的裝配策略如何,按名稱仍是類型?ui
2. 爲構造方法,字段和方法添加Autowired註解以後,誰來解析這個Autowired註解,完成裝配this
3. 裝配的bean從何處而來,是在Spring的xml文件中定義的bean嗎?spa
從Autowired的javadoc中獲得以下信息3d
1. AutowiredAnnotationBeanPostProcessor負責掃描Autowired註解,而後完成自動注入code
2. 能夠對私有的字段使用Autowired進行自動裝配,而無需爲私有字段定義getter/setter來read/write這個字段component
3. 使用Autowired註解的類方法,能夠是任意的方法名,任意的參數,Spring會從容器中找到合適的bean進行裝配,setter自動注入跟對字段自動注入效果同樣orm
當項目中使用了Autowired註解時,須要明確的告訴Spring,配置中引用了自動注入的功能,在Spring的配置文件,作法有兩種
1. 配置AutowiredAnnotationBeanPostProcessor
2. 使用context:annotation-config/。context:annotationconfig/ 將隱式地向 Spring 容器註冊AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
、PersistenceAnnotationBeanPostProcessor
以及equiredAnnotationBeanPostProcessor
這 4 個 BeanPostProcessor。
UserSerice依賴的UserDao使用Autowired註解,
UserDao沒有在Spring配置文件中定義
結果:UserDao爲null
UserSerice依賴的UserDao使用Autowired註解
UserDao在Spring配置文件中有定義
結果:UserDao爲null
UserSerice依賴的UserDao使用Autowired註解
UserDao在Spring配置文件中有定義
Spring中使用context:annotation-config/
** 結果:UserDao正確注入,在Spring中配置的UserDao的實現,而在UserService中的是UserDao的接口,也就是說,雖然它們類型沒有徹底匹配,可是因爲是實現**
關係,Spring仍然可以完成自動注入
UserSerice依賴的UserDao使用Autowired註解
UserDao在Spring配置文件中有定義
Spring中配置AutowiredAnnotationBeanPostProcessor
結果:UserDao正確注入,同實例三
UserSerice依賴的UserDao使用Autowired註解
UserDao在Spring配置文件中有兩份定義(id不一樣)
Spring中使用context:annotation-config/
結果:
1. 若是UserDao的屬性名與某個bean的id相同,那麼按照屬性名和id名稱匹配原則,自動裝配
2. 若是UserService中定義的UserDao的屬性名,與Spring配置文件中的兩個id都不一樣,那麼注入失敗,異常拋出,提示,沒法完整自動裝配
1. 使用Autowired自動裝配,必須在Spring的配置文件中使用context:annotation-config/來告訴Spring須要進行自動裝配掃描(AutowiredAnnotationBeanPostProcessor不推薦使用)
2. Autowired默認按類型進行匹配,當匹配到多個知足條件的bean時,再按照屬性名和bean的id進行匹配,若是仍然有多個匹配上或者沒有一個匹配上,則拋出異常,提示自動裝配失敗
3. 在使用Autowired時,能夠使用Qualifier註解,顯式的指定,當衝突發生時,使用那個id對應的bean
4. Autowired註解自動裝配功能完成的是依賴的自動注入,所以,在一個bean中,它依賴的bean能夠經過自動注入的方式完成而不須要顯式的爲它的屬性進行注入。可是這些依賴的bean仍然不能省略,仍是要在Spring中進行配置,省略的僅僅是bean屬性的注入配置代碼
Resource註解在功能和目的上,等效於Autowried+Qualifier註解,Resource註解是JSR-250規範的一部分,它定義在JDK的javax.annoation包中,以下是它的定義:
package javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/** * The Resource annotation marks a resource that is needed * by the application. This annotation may be applied to an * application component class, or to fields or methods of the * component class. When the annotation is applied to a * field or method, the container will inject an instance * of the requested resource into the application component * when the component is initialized. If the annotation is * applied to the component class, the annotation declares a * resource that the application will look up at runtime. <p> * * Even though this annotation is not marked Inherited, deployment * tools are required to examine all superclasses of any component * class to discover all uses of this annotation in all superclasses. * All such annotation instances specify resources that are needed * by the application component. Note that this annotation may * appear on private fields and methods of superclasses; the container * is required to perform injection in these cases as well. * * @since Common Annotations 1.0 */
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
/** * The JNDI name of the resource. For field annotations, * the default is the field name. For method annotations, * the default is the JavaBeans property name corresponding * to the method. For class annotations, there is no default * and this must be specified. */
String name() default "";
/** * The name of the resource that the reference points to. It can * link to any compatible resource using the global JNDI names. * * @since Common Annotations 1.1 */
String lookup() default "";
/** * The Java type of the resource. For field annotations, * the default is the type of the field. For method annotations, * the default is the type of the JavaBeans property. * For class annotations, there is no default and this must be * specified. */
Class<?> type() default java.lang.Object.class;
/** * The two possible authentication types for a resource. */
enum AuthenticationType {
CONTAINER,
APPLICATION
}
/** * The authentication type to use for this resource. * This may be specified for resources representing a * connection factory of any supported type, and must * not be specified for resources of other types. */
AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
/** * Indicates whether this resource can be shared between * this component and other components. * This may be specified for resources representing a * connection factory of any supported type, and must * not be specified for resources of other types. */
boolean shareable() default true;
/** * A product specific name that this resource should be mapped to. * The name of this resource, as defined by the <code>name</code> * element or defaulted, is a name that is local to the application * component using the resource. (It's a name in the JNDI * <code>java:comp/env</code> namespace.) Many application servers * provide a way to map these local names to names of resources * known to the application server. This mapped name is often a * <i>global</i> JNDI name, but may be a name of any form. <p> * * Application servers are not required to support any particular * form or type of mapped name, nor the ability to use mapped names. * The mapped name is product-dependent and often installation-dependent. * No use of a mapped name is portable. */
String mappedName() default "";
/** * Description of this resource. The description is expected * to be in the default language of the system on which the * application is deployed. The description can be presented * to the Deployer to help in choosing the correct resource. */
String description() default "";
}
複製代碼
Autowried註解,首先根據類型匹配,若是類型匹配到多個,那麼在根據屬性名和bean的id進行匹配(能夠由Qualifier註解強制匹配指定的bean id)。Resource註解則順序不一樣,它有以下幾種可能的狀況:
策略:首先進行按名稱匹配策略: 匹配name屬性和bean的id,若是匹配,則判斷查找到的bean是不是type屬性指定的類型,若是是type屬性指定的類型,則匹配成功。若是不是type屬性指定的類型,則拋出異常,提示匹配失敗;若是name屬性跟bean的id不匹配,則拋出異常提示沒有bean的id匹配name屬性
策略:查找bean的id爲name屬性的bean,查找到,不關心類型爲何,都是匹配成功;若是找不到name屬性指定的bean id,則匹配失敗,拋出異常
策略:首先進行按名稱匹配策略: 匹配屬性名和bean的id,若是匹配,則判斷查找到的bean是不是type屬性指定的類型,若是是type屬性指定的類型,則匹配成功。若是不是type屬性指定的類型,則拋出異常,提示匹配失敗;其次進行按類型匹配策略: 若是屬性名跟bean的id不匹配,則查找類型爲type的bean,若是僅僅找到一個,自動裝配成功,其它狀況失敗。
策略:首先進行按屬性名匹配策略,匹配則注入成功;若是屬性名不匹配,則進行類型匹配策略,只有爲一個類型匹配才成功,其餘狀況都失敗