spring beans源碼解讀之--Bean的註解(annotation)

隨着spring註解的引入,愈來愈多的開發者開始使用註解,這篇文章將對註解的機制進行串聯式的講解,不求深刻透徹,但求串起spring beans註解的珍珠,展現給你們。java

1. spring beans經常使用的註解:spring

  public @interface Autowired:能夠對成員變量、方法和構造函數進行標註,來完成自動裝配的工做。express

Marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities.
Only one constructor (at max) of any given bean class may carry this annotation, indicating the constructor to autowire when used as a Spring bean. Such a constructor does not have to be public.

Fields are injected right after construction of a bean, before any config methods are invoked. Such a config field does not have to be public. Config methods may have an arbitrary name and any number of arguments; each of those arguments will be autowired with a matching bean in the Spring container. Bean property setter methods are effectively just a special case of such a general config method. Such config methods do not have to be public. In the case of multiple argument methods, the 'required' parameter is applicable for all arguments. In case of a Collection or Map dependency type, the container will autowire all beans matching the declared value type. In case of a Map, the keys must be declared as type String and will be resolved to the corresponding bean names. Note that actual injection is performed through a BeanPostProcessor which in turn means that you cannot use @Autowired to inject references into BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation). Since: 2.5

  public @interface Configurable @Configurable 註解中的autowire屬性就可讓Spring來自動裝配了: @Configurable(autowire=Autowire.BY_TYPE) 或者 @Configurable(autowire=Autowire.BY_NAME,這樣就能夠按類型或者按名字自動裝配了。編程

Marks a class as being eligible for Spring-driven configuration.
Typically used with the AspectJ AnnotationBeanConfigurerAspect.

Since:
2.0
public @interface Value:用於注入SpEL表達式,能夠放置在字段方法或參數上。
Annotation at the field or method/constructor parameter level that indicates a default value expression for the affected argument. Typically used for expression-driven dependency injection. Also supported for dynamic resolution of handler method parameters, e.g. in Spring MVC. A common use case is to assign default field values using "#{systemProperties.myProp}" style expressions. Note that actual processing of the @Value annotation is performed by a BeanPostProcessor which in turn means that you cannot use @Value within BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation). Since: 3.0
public @interface Qualifier:指定限定描述符,對應於基於XML配置中的<qualifier>標籤,@Qualifier限定描述符除了能根據名字進行注入,但能進行更細粒度的控制如何選擇候選者
@Qualifier(value = "限定標識符") 。
This annotation may be used on a field or parameter as a qualifier for candidate beans when autowiring. It may also be used to annotate other custom annotations that can then in turn be used as qualifiers.
Since:
2.5
public @interface Required 依賴檢查;
Marks a method (typically a JavaBean setter method) as being 'required': that is, the setter method must be configured to be dependency-injected with a value.
Please do consult the javadoc for the RequiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation). Since: 2.0

 

2. 註解bean的定義AnnotatedBeanDefinitionapi

public interface AnnotatedBeanDefinition extends BeanDefinition {

    /**
     * Obtain the annotation metadata (as well as basic class metadata)
     * for this bean definition's bean class.
     * @return the annotation metadata object (never {@code null})
     */
    AnnotationMetadata getMetadata();

}

   該接口繼承了BeanDefinition,提供了一個getMetadata()方法來獲取該bean definition的註解元數據。數組

其中,AnnotationMetadata定義了訪問特定類的註解的抽象接口,它不須要加載該類便可訪問。app

public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
}
ClassMetadata定義了一個特定類的抽象元數據,不須要加載此類。主要方法以下:
String getClassName()返回該類的名稱。boolean isInterface()返回該類是不是接口。boolean isAbstract()返回該類是否爲抽象類。boolean isConcrete()返回該類是否爲具體類。boolean isFinal()返回該類是否爲final類boolean hasSuperClass()返回該類是否有父類
String getSuperClassName()返回父類的名稱,沒有的話返回null.
String[] getInterfaceNames()返回繼承的接口數組,若是沒有,返回空.
String[] getMemberClassNames()返回引用的類的名稱。

AnnotatedTypeMetadata定義訪問特定類型的註解,不須要加載類。主要方法有:ide

boolean isAnnotated(String annotationType)是否有匹配的註解類型
Map<String,Object> getAnnotationAttributes(String annotationType,boolean classValuesAsString)獲取特定類型註解的屬性

AnnotationMetadata的標準實現類StandardAnnotationMetadata,它使用標準的反射來獲取制定類的內部註解信息。主要方法有:函數

getAllAnnotationAttributes(String annotationType) 
getAnnotatedMethods(String annotationType) 
hasMetaAnnotation(String annotationType) 
isAnnotated(String annotationType) 
hasAnnotatedMethods(String annotationType) 

AnnotationMetadata還有一個子類:AnnotationMetadataReadingVisitor,它是字節碼訪問實現。post

class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata {
}

讓咱們瞭解一下visitor模式:

定義:

The Gang of Four defines the Visitor as: "Represent an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates."—″≤

The nature of the Visitor makes it an ideal pattern to plug into public APIs thus allowing its clients to perform operations on a class using a 「visiting」 class without having to modify the source.

uml 結構圖以下:

 小結:vistor設置模式把狀態抽象出來成爲一個接口(訪問者),不一樣的狀態就做爲狀態的不一樣實現類(不一樣的訪問者)。

 3. 註解bean的實現類

    3.1 AnnotatedGenericBeanDefinition

          繼承了GenericBeanDefinition,增長了對註解元素的支持,這種支持是經過AnnotationBeanDefinition暴露的的註解元素接口。

    GenericBeanDefinition主要用來測試AnnotatedBeanDefinition上的操做的,例如:在spring的component掃描支持的實現中(默認實現類是ScannedGenericBeanDefinition,它一樣實現了AnnotatedBeanDefinition接口)

  3.2 ConfigurationClassBeanDefinition

    ConfigurationClassBeanDefinition是ConfigurationClassBeanDefinitionReader的內部類,ConfigurationClassBeanDefinitionReader讀取一組徹底填充了屬性的配置實例,經過context內給定的BeanDefinitionRegistry進行註冊bean definition。這個類在BeanDefinitionReader這層後就改造,但沒有繼承或者擴展配置類。

   3.3 ScannedGenericBeanDefinition

   基於asm的類解析器,是GenericBeanDefinition類的擴展,支持註解元數據,這種支持經過AnnotatedBeanDefinition接口實現。

4. 註解的解析與處理

4.1 @Autowired註解實現AutowiredAnnotationBeanPostProcessor

   

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
}
AutowiredAnnotationBeanPostProcessor 間接繼承了BeanPostProcessor,它自動綁定註解的field,setter方法和任意的配置方法。當檢測到5個java註解時這些成員被注入其中。spring默認的註解爲@Autowired和@Value。
另外:也支持JSR-330的@inject註解,做爲@Autowired的替代方案。

當制定bean 類的惟一構造方法帶有required 註解參數,且required值設置爲true時,代表看成爲spring一個bean時,構造方法默認自動綁定。若多個構造方法帶有non-required 註解參數,它們將做爲自動綁定的候選項。帶有大量依賴的構造方法能夠經過spring容器中的匹配的bean來構造,若是沒有候選者知足條件,則會使用默認的構造器。註解構造器不必定是public的。
Field注入是在構造方法以後,配置方法以前,這種配置field不要求必定爲public
配置方法能夠有任意的名稱和不定的參數列表,這些參數則被自動注入到spring容器中的匹配的bean。bean的屬性setter方法僅僅是通用的配置方法的一個特例而已。配置方法不要求方法必定爲public
注意:默認註冊AutowiredAnnotationBeanPostProcessor的方式有<context:annotation-config> 和<context:component-scan> xml標籤,若是你指定了一個自定義的AutowiredAnnotationBeanPostProcessor bean definition,移除或者關閉默認的註解配置。

其中,MergedBeanDefinitionPostProcessor的定義以下:
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

    /**
     * Post-process the given merged bean definition for the specified bean.
     * @param beanDefinition the merged bean definition for the bean
     * @param beanType the actual type of the managed bean instance
     * @param beanName the name of the bean
     */
    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

}
BeanPostProcessor 是一個能夠定製修改一個新的bean實例的工廠鉤子,例如:檢查marker接口或者使用代理包裝他們。
applicationContext能夠在他們的bean容器中自動識別BeanPostProcessor bean,並將它們應用到接下來所建立的bean。通常的bean factory經過編程來註冊Post-processor,並將它們應用到整個bean factory建立bean的過程當中。

一般意義上,post-processor 設置bean屬性經過marker 接口或者相似於實現postProcessBeforeInitialization(java.lang.Object, java.lang.String);使用代理包裝bean一般實現postProcessAfterInitialization(java.lang.Object, java.lang.String).

4.2 @configurable註解實現AnnotationBeanWiringInfoResolver 

設置 @Configurable 註解中的autowire屬性就可讓Spring來自動裝配了: @Configurable(autowire=Autowire.BY_TYPE) 或者 @Configurable(autowire=Autowire.BY_NAME,這樣就能夠按類型或者按名字自動裝配了。

    AnnotationBeanWiringInfoResolver 繼承自BeanWiringInfoResolver,BeanWiringInfoResolver使用configurable註解來查找哪些類須要自動綁定。

public class AnnotationBeanWiringInfoResolver implements BeanWiringInfoResolver {
}

實現了BeanWiringInfoResolver的resolveWiringInfo方法

@Override
    public BeanWiringInfo resolveWiringInfo(Object beanInstance) {
        Assert.notNull(beanInstance, "Bean instance must not be null");
        Configurable annotation = beanInstance.getClass().getAnnotation(Configurable.class);
        return (annotation != null ? buildWiringInfo(beanInstance, annotation) : null);
    }

    /**
     * Build the BeanWiringInfo for the given Configurable annotation.
     * @param beanInstance the bean instance
     * @param annotation the Configurable annotation found on the bean class
     * @return the resolved BeanWiringInfo
     */
    protected BeanWiringInfo buildWiringInfo(Object beanInstance, Configurable annotation) {
        if (!Autowire.NO.equals(annotation.autowire())) {
            return new BeanWiringInfo(annotation.autowire().value(), annotation.dependencyCheck());
        }
        else {
            if (!"".equals(annotation.value())) {
                // explicitly specified bean name
                return new BeanWiringInfo(annotation.value(), false);
            }
            else {
                // default bean name
                return new BeanWiringInfo(getDefaultBeanName(beanInstance), true);
            }
        }
    }

 4.3 @qualifier的註解實現類QualifierAnnotationAutowireCandidateResolver

 

public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
}

public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandidateResolver, BeanFactoryAware {
}

其中,AutowireCandidateResolver是一個策略接口,由它來決定特定的bean definition對特定的依賴是否能夠做爲一個自動綁定的候選項,它的主要方法有:

boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor)

Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor,String beanName)

Object getSuggestedValue(DependencyDescriptor descriptor)

 QualifierAnnotationAutowireCandidateResolver間接實現了AutowireCandidateResolver,對要自動綁定的field或者參數和bean definition根據@qualifier註解進行匹配。同時也支持經過@value註解來綁定表達式的值。

另外,還只是JSR-330的javax.inject.Qualifier註解。

4.4 @required註解實現類RequiredAnnotationBeanPostProcessor。

public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
}

和AutowiredAnnotationBeanPostProcessor同樣,間接繼承自BeanPostProcessor,它增長了對javaBean屬性配置的約束,java 5 註解能夠檢測bean的required屬性,spring默認是@Required註解。

注意:默認註冊AutowiredAnnotationBeanPostProcessor的方式有<context:annotation-config> 和<context:component-scan> xml標籤,若是你指定了一個自定義的
默認註冊AutowiredAnnotationBeanPostProcessor的方式有<context:annotation-config> 和<context:component-scan> xml標籤,若是你指定了一個自定義的AutowiredAnnotationBeanPostProcessor bean definition,移除或者關閉默認的註解配置。其他和AutowiredAnnotationBeanPostProcessor相似,不一一贅述了。

4.5 初始化和銷燬方法的註解實現類InitDestroyAnnotationBeanPostProcessor

public class InitDestroyAnnotationBeanPostProcessor
        implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
}

InitDestroyAnnotationBeanPostProcessor間接繼承了BeanPostProcess,實現了經過註解來初始化和銷燬方法,是spring的InitializingBean和DisposableBean回調接口的註解實現。

它經過"initAnnotationType"和"destroyAnnotationType"屬性來檢查指定的註解類型,任何自定義的註解均可以使用。

初始化和銷燬註解能夠用在任意可見的方法:public,package-protected,protected,private等。儘管能夠對多個方法進行註解,但咱們推薦只在一個初始化和銷燬方法上各自進行註解。

 

小結:

 Spring3的基於註解實現Bean依賴注入支持以下三種註解:
Spring自帶依賴注入註解: Spring自帶的一套依賴注入註解;
JSR-250註解:Java平臺的公共註解,是Java EE 5規範之一,在JDK6中默認包含這些註解,從Spring2.5開始支持。
JSR-330註解:Java 依賴注入標準,Java EE 6規範之一,可能在加入到將來JDK版本,從Spring3開始支持;

其中,
Spring自帶依賴注入註解

1 @Required:依賴檢查;
2 @Autowired:自動裝配2 
自動裝配,用於替代基於XML配置的自動裝配
基於@Autowired的自動裝配,默認是根據類型注入,能夠用於構造器、字段、方法注入
3 @Value:注入SpEL表達式
用於注入SpEL表達式,能夠放置在字段方法或參數上
@Value(value = "SpEL表達式")  
@Value(value = "#{message}")  
4 @Qualifier:限定描述符,用於細粒度選擇候選者
@Qualifier限定描述符除了能根據名字進行注入,但能進行更細粒度的控制如何選擇候選者
@Qualifier(value = "限定標識符") 


JSR-250註解

1 @Resource:自動裝配,默認根據類型裝配,若是指定name屬性將根據名字裝配,可使用以下方式來指定
@Resource(name = "標識符")  
字段或setter方法 

2 @PostConstruct和PreDestroy:經過註解指定初始化和銷燬方法定義

 

JSR-330註解
1 @Inject:等價於默認的@Autowired,只是沒有required屬性
2 @Named:指定Bean名字,對應於Spring自帶@Qualifier中的缺省的根據Bean名字注入狀況
3 @Qualifier:只對應於Spring自帶@Qualifier中的擴展@Qualifier限定描述符註解,即只能擴展使用,沒有value屬性

參考文獻:   1. http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/annotation/   2. http://blog.csdn.net/wangshfa/article/details/9712379
相關文章
相關標籤/搜索