1. 程式人生 > >Spring IOC原理原始碼解析(@Autowired原理詳解 :標識建構函式)(一 )

Spring IOC原理原始碼解析(@Autowired原理詳解 :標識建構函式)(一 )

IOC,inversion of control 控制反轉,有時候也叫DI,dependency injection 依賴注入,是一種程式碼解耦的方式。

在一個類中定義一個屬性,正常情況下需要在此類中有對此屬性賦值的程式碼,如setter方法,或者在建構函式中賦值,因此類和屬性之間的關係已經確定下來了,類和屬性間就有了一定的耦合關係。而IOC的精髓就是解耦,類中沒有顯式的對屬性的賦值程式碼,同時屬性的實際型別和值在執行時有系統動態的賦值,Spring對IOC做了很大的擴充套件,使用者可以很靈活的控制注入的物件型別及值。

Spring內IOC的最直接體現就是@Autowired註解,最常用的方式就是表示在屬性上,Spring容器在啟動時會將容器內型別是標識了@Autowired的屬性型別或者其子類,實現類的Bean通過反射的形式賦值給此屬性,或者叫注入的此類中。

Spring中對@Autowired註解的解析是通過一個叫AutowiredAnnotationBeanPostProcessor的BeanPostProcessor(Bean的後處理器)來進行的。BeanPostProcessor負責Bean的一系列處理,例項化前後,初始化前後燈階段執行相應方法,具體方法的執行順序如下:


                    BeanPostPrecessors Invoke Procedure(執行流程)

1.InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
(Class<?> beanClass, String beanName);
invoke before doCreateBean(),if the method returns not null,the return Object will as the Bean, avoid invoke doCreateBean() ; 2.SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors(Class<?> beanClass, String beanName); used to
determine to use which Constructor to instance Bean; 3.MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName); the Bean gets instantiated, modify the RootBeanDefinition ,such as adding PropertyValue etc. before populate Bean; 4.SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference(Object bean, String beanName); invoke before populate Bean,used for resolve Circular Reference; 5.InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(Object bean, String beanName); invoke in populate Bean, but before fill in values,return false will break the opreation for filling values in Bean; 6.InstantiationAwareBeanPostProcessor.postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName); invoke in populate Bean, but before fill in values,modify the PropertyValues which will be apply for the Bean, return null will break the opreation for filling values in Bean; 7.BeanPostProcessor.postProcessBeforeInitialization(Object bean, String beanName); invoked before invokeInitMethods, modify the finally Bean instance 8.BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName); invoked after invokeInitMethods, modify the finally Bean instance

使用者可以自己定義自己的BeanPostProcessor,將其以Bean的形式註冊到Spring容器中,Spring容器在啟動時會執行其相應方法。

AutowiredAnnotationBeanPostProcessor在Spring容器初始化時會最先執行determineCandidateConstructors方法,先看起原始碼:

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
        //此方法的含義是解析Bean類裡建構函式上的@Autowired註解,如果有合適的標識了@Autowired的建構函式,
        //則在例項化此Bean時會使用此建構函式,@Import和@ComponentScan得到的Bean會如此解析,
        //@Bean標識方法生成的Bean不會如此
        public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
            throws BeanCreationException {

        // Let's check for lookup methods here..
        if (!this.lookupMethodsChecked.contains(beanName)) {
            try {
                ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
                    @Override
                    public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                        Lookup lookup = method.getAnnotation(Lookup.class);
                        if (lookup != null) {
                            LookupOverride override = new LookupOverride(method, lookup.value());
                            try {
                                RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
                                mbd.getMethodOverrides().addOverride(override);
                            }
                            catch (NoSuchBeanDefinitionException ex) {
                                throw new BeanCreationException(beanName,
                                        "Cannot apply @Lookup to beans without corresponding bean definition");
                            }
                        }
                    }
                });
            }
            catch (IllegalStateException ex) {
                throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
            }
            catch (NoClassDefFoundError err) {
                throw new BeanCreationException(beanName, "Failed to introspect bean class [" + beanClass.getName() +
                        "] for lookup method metadata: could not find class that it depends on", err);
            }
            this.lookupMethodsChecked.add(beanName);
        }

        // Quick check on the concurrent map first, with minimal locking.
        Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
        if (candidateConstructors == null) {
            // Fully synchronized resolution now...
            synchronized (this.candidateConstructorsCache) {
                //對每個類的建構函式只解析一次,解析完會儲存結果,以備下次服用
                candidateConstructors = this.candidateConstructorsCache.get(beanClass);
                if (candidateConstructors == null) {
                    Constructor<?>[] rawCandidates;
                    try {
                        rawCandidates = beanClass.getDeclaredConstructors();
                    }
                    catch (Throwable ex) {
                        throw new BeanCreationException(beanName,
                                "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                                "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                    }
                    List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
                    Constructor<?> requiredConstructor = null;
                    Constructor<?> defaultConstructor = null;
                    for (Constructor<?> candidate : rawCandidates) {
                        //檢視建構函式上是否標識@Autowired註解,獲取註解的屬性
                        AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                        if (ann == null) {
                            Class<?> userClass = ClassUtils.getUserClass(beanClass);
                            if (userClass != beanClass) {
                                try {
                                    Constructor<?> superCtor =
                                            userClass.getDeclaredConstructor(candidate.getParameterTypes());
                                    //如果此建構函式是過載了父類的建構函式,則尋找父類的建構函式,檢視是否標識@Autowired註解,獲取註解的屬性
                                    ann = findAutowiredAnnotation(superCtor);
                                }
                                catch (NoSuchMethodException ex) {
                                    // Simply proceed, no equivalent superclass constructor found...
                                }
                            }
                        }
                        //當建構函式上存在@Autowired註解
                        if (ann != null) {
                            //@Autowired預設的required = true,當有一個required = true的@Autowired標識的建構函式時,
                            //不能有其他的建構函式再標識@Autowired,否則會報錯
                            if (requiredConstructor != null) {
                                throw new BeanCreationException(beanName,
                                        "Invalid autowire-marked constructor: " + candidate +
                                        ". Found constructor with 'required' Autowired annotation already: " +
                                        requiredConstructor);
                            }
                            //@Autowired的required的屬性值,true / false
                            boolean required = determineRequiredStatus(ann);
                            if (required) {
                                if (!candidates.isEmpty()) {
                                    throw new BeanCreationException(beanName,
                                            "Invalid autowire-marked constructors: " + candidates +
                                            ". Found constructor with 'required' Autowired annotation: " +
                                            candidate);
                                }
                                requiredConstructor = candidate;
                            }
                            candidates.add(candidate);
                        } 
                        else if (candidate.getParameterTypes().length == 0) {
                            defaultConstructor = candidate;
                        }
                    }
                    if (!candidates.isEmpty()) {
                        // Add default constructor to list of optional constructors, as fallback.
                        ////當沒有建構函式標識@Autowired時,設定預設的建構函式作為額外選擇
                        if (requiredConstructor == null) {
                            if (defaultConstructor != null) {
                                candidates.add(defaultConstructor);
                            }  //如果沒有預設的無參建構函式,且有@Autowired(required = false)的建構函式,則發出警告信
                            else if (candidates.size() == 1 && logger.isWarnEnabled()) {
                                logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
                                        "': single autowire-marked constructor flagged as optional - " +
                                        "this constructor is effectively required since there is no " +
                                        "default constructor to fall back to: " + candidates.get(0));
                            }
                        }
                        candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
                    }  //若只有一個建構函式,且沒標識@Autowired,其引數長度>0,將其作為候選者
                    else if (rawCandidates.length == 1 && rawCandidates[0].getParameterTypes().length > 0) {
                        candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
                    } //沒有合適的建構函式
                    else {
                        candidateConstructors = new Constructor<?>[0];
                    }
                    this.candidateConstructorsCache.put(beanClass, candidateConstructors);
                }
            }
        }
        return (candidateConstructors.length > 0 ? candidateConstructors : null);
    }

}

AutowiredAnnotationBeanPostProcessor篩選@Autowired標識的建構函式的程式碼就是這些,篩選出這些建構函式之後,Spring使用ConstructorResolver這個類來擇取合適的建構函式,流程如下:

  1. 首先對這些建構函式按修飾符優先public排序,修飾符相同再按引數的長短排序,最先解析引數最長的public修飾的建構函式,其優先順序最高.
  2. 對建構函式的每一個引數解析,如果每一個引數均能從Spring容器中找到合適的Bean,則此將此建構函式作為最優解,如果容器內Bean不能滿足所有引數,則解析下一個建構函式。
  3. 如果存在兩個引數長度相同的建構函式,且容器內Bean均能滿足引數解析,則按引數型別和Bean型別的差異性求取引數的差異權重,比如引數是介面,Bean是實現類,則差異加2,引數是集合,Bean是單個類,則轉換成集合,差異加2等等,比較兩個建構函式的差異權重大小,差異小的那個作為最優解。如果兩個差異權重相等,則丟擲含有模稜兩可的建構函式的BeanCreationException。
  4. 當有了最優解的建構函式後,如果下一個建構函式的引數長度等於最優解,則解析此建構函式,如果引數長度小於最優解,則不再解析,直接忽略之後的所有建構函式。
  5. 當得到了建構函式最優解之後,將此建構函式存入此Bean的BeanDefinition中,以備下次複用,就是說只對建構函式候選者集合解析一次,下次例項化Bean的時候可以直接得到這個最優解。
  6. 以上的情況是基於Spring容器例項化Bean的情況,就是例項化時不會附帶Arguments,就是不帶引數,如果是使用者自己例項化Bean時,通過BeanFactory的 Object getBean(String name, Object… args) throws BeansException; T getBean(Class requiredType, Object… args) throws BeansException;方法例項化時,按照建構函式的順序傳入例項化引數,則Spring在找合適的建構函式時會忽略之前快取的最優解,以同樣的順序解析建構函式候選者集合,看看哪些建構函式的引數適合傳入的引數,找不到合適的則跑出BeanCreationException。

以上就是@Autowired註解在建構函式上的用法的原理及流程。

重點: BeanFactory的getBean()方法獲取scope = singleton的Bean時,不會生成新的Bean物件,
在scope為request及session的生命週期內,Bean的例項化只會觸發一次,也就是說@Autowired的標識的建構函式不是每次呼叫getBean()均會觸發執行。只有scope = prototype的Bean,才會每次均執行。