1. 程式人生 > >Spring中Bean的例項化與DI的過程

Spring中Bean的例項化與DI的過程

引言

前文我們介紹了關於如何學習Spring的原始碼以及解析了spring中載入配置檔案註冊Beandefinition的過程。今天我們繼續學習DI的過程。

建立例項和DI過程

IOC和DI都是對spring容器特性的描述。IOC指的是將例項的生命週期交給第三方管理(spring)。而DI的側重點在於某一個類依賴了其他的例項,將例項注入到依賴它的例項的過程。所以可以很明顯的看出來DI是發生在類例項已經例項化完成之後的。

建立例項

BeanDefinition

BeanDefinition是對bean屬性的定義,包含了bean的狀態的屬性,如bean的Class物件,單例還是原型等。

上圖中是BeanDefinition定義的方法,可以看出其中包括建立Bean的工廠類名稱和bean的狀態單例,懶載入等。

其中大多數方法都很容易理解,有幾個屬性這裡需要解釋下。

dependsOn

dependsOn是指當前Beandefinition所表示的Bean依賴了其他那些bean(不包括基本資料型別),這裡依賴的bean並不需要在當前Bean中宣告,所以不能通過依賴注入完成,而是需要顯示的定義。

autowireCandidate

autowireCandidate用來表示當前bean是否可以被注入到其他例項中。

上面的內容都可以通過xml配置或者註解來配置。

xml

<bean scope="singleton" autowire-candidate="true" init-method="" factory-method="" lazy-init="true" >
    </bean>

註解

public class JavaBean {
    
    public void init(){
        //init
    }

    public void destroy(){
        //destroy
    }
    
    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public JavaBean getEntity(){
        return new JavaBean();
    }
}
繼承體系

在上圖中實際實際被用來實現Beandefinition的類是RootBeanDefinitionChildBeanDefinitionGenericBeanDefinition。其中GenericBeanDefinition是在spring2.5以後才出現的,spring2.5以後都建議使用GenericBeanDefinition。但是由於以前的程式碼都是使用RootBeanDefinitionChildBeanDefinition,所以我們也還能看到RootBeanDefinitionChildBeanDefinition這些類。

大體流程

同IOC一樣在閱讀原始碼前先來看看一DI的大體流程。

refresh()

在閱讀IOC相關實現的時候,除開建構函式外refresh()就是我們最初的入口,當時只是看了其中的部分程式碼。實際上refresh()貫穿了spring啟動的整個階段。當refresh()方法執行完成時基本就代表spring正常啟動了。在DI篇我們來繼續看refresh()的其他的一些程式碼。

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //讀取配置檔案 註冊Beandefinition
            prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            prepareBeanFactory(beanFactory);

            try {

                postProcessBeanFactory(beanFactory);
                invokeBeanFactoryPostProcessors(beanFactory);

                registerBeanPostProcessors(beanFactory);

                initMessageSource();

                initApplicationEventMulticaster();

                onRefresh();

                registerListeners();

                finishBeanFactoryInitialization(beanFactory);

                finishRefresh();
            }catch (BeansException ex) {
                logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

                destroyBeans();

                cancelRefresh(ex);
                throw ex;
            }
        }
    }

BeanFactoryPostProcessor和BeanPostProcessor

在進行bean的例項化之前會先執行BeanFactoryPostProcessor和註冊BeanPostProcessor


BeanFactoryPostProcessor

public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

BeanFactoryPostProcessor可以對BeanDefinition進行處理。BeanFactoryPostProcessor在容器實際例項化任何其它的bean之前讀取bean的元資料,並且可以對其進行修改修改。用於在執行例項化bean之前進行呼叫。


BeanPostProcessor

public interface BeanPostProcessor {

Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
```

實現BeanPostProcessor介面可以在Bean初始化的前後做一些自定義的操作,但是不能夠直接操作BeanDefinition元資料。

BeanFactoryPostProcessorBeanPostProcessor都是spring留給我們進行擴充套件的類。通過實現這兩個介面我們可以在bean的例項化過程中新增一些自定義的操作。而需要注意的是這兩個介面雖然都提供了擴充套件bean例項化的功能,但兩者確實完全不同的:

  • BeanFactoryPostProcessor是在所有的bean都未開始例項化前呼叫,其可以拿到容器中所有的Beandefinition,所以可以在bean例項化前直接修改bean定義的元資料。
  • BeanPostProcessor裡的例項化前後指的是呼叫init(init-method)方法前後,這時實際上bean已經開始了例項化(詳細的可以參考類的例項化全過程),這時取到的僅僅是某一指定類的例項。即使進行修改也只是修改當前這一例項,而無法對bean的元資料修改。

由於postProcessor可能會在bean的例項化之前進行呼叫,所以在例項化前context肯定需要先拿到postProcessor,這也就可以解釋上面的程式碼中在解析完配置檔案後就開始註冊BeanFactoryPostProcessorBeanPostProcessor

listener

//tood

具體的關於postProcessor和Listener相關會在將整體流程理順後再詳細介紹。

finishBeanFactoryInitialization(ConfigurableListableBeanFactory)

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }

    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    
    beanFactory.setTempClassLoader(null);
    //快取bean定義
    beanFactory.freezeConfiguration();
    beanFactory.preInstantiateSingletons();
}
方法首先查詢是否開啟了註冊conversionService,conversionService是用於進行兩個類轉換的,例如之前說過了Environment類就依賴該例項將定義的變數轉換為相應的型別。

如果要開啟註冊conversionService,可以在配置檔案中配置。



接下來的程式碼是從bean定義中獲取LoadTimeWeaverAware型別優先進行例項化。LoadTimeWeaverAware作用是當類被載入進jvm是動態的轉換類。之所以優先例項化這些類是因為在例項化其他類時可能會使用到這些類,比如jpa就極度依賴這些功能。

### preInstantiateSingletons()

public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

    for (String beanName : beanNames) {
        //獲取bean定義
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        //抽象類無法例項化
        //非單例和懶載入在需要時才例項化
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                //獲取factoryBean的例項
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                        @Override
                        public Boolean run() {
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                }else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    getBean(beanName);
                }
            }else {
                getBean(beanName);
            }
        }
    }

    // 實現了SmartInitializingSingleton介面的回撥方法
    // SmartInitializingSingleton介面同InitializingBean介面類似都是用於在建立bean時進行一些後置的操作 
    // 不同之處在於InitializingBean是在每一個例項化的過程中進行呼叫 而SmartInitializingSingleton是在所有的單例bean被例項化後再refresh中進行回撥
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }
                }, getAccessControlContext());
            }else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

```

preInstantiateSingletons通過一個for迴圈來例項化所有註冊到容器中的bean定義所代表的的bean。

在確定好每一個beanName所代表的的bean確實需要例項化後首先檢查當前beanName是否實現了介面


而由於```FactoryBean```本身首先是一個bean,所以我們也可以在ioc容器中獲取該bean的例項。如果我們通過getBean(beanName)方法獲取的實際上是```FactoryBean```產生的例項型別,想要獲取```FactoryBean```的例項需要使用```getBean("&" + beanName)```。

#### getBean(String)

getBean是一個過載方法,主要還是呼叫doGetBean()方法實現功能。

protected <T> T doGetBean(
        final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
        throws BeansException {
    //取該beanName在容器中儲存的name
    //比如上面介紹的factoryBean會加一個& 以及給bean配置的別名等
    final String beanName = transformedBeanName(name);
    Object bean;
    //嘗試從儲存bean的容器中取,如果已經存在則不用再次例項化
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }else {
        //對於非單例bean 如果該bean正在被建立而又嘗試再次建立則會直接丟擲異常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            //!containsBeanDefinition(beanName)表示從當前容器中沒有找到匹配的BeanDefinition 嘗試從父容器中查詢
            String nameToLookup = originalBeanName(name);
            if (args != null) {
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }else {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        if (!typeCheckOnly) {
            //標記當前beanName所表示的bean正在被建立或已經被建立
            markBeanAsCreated(beanName);
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            //這一步根據其實現貌似主要是檢查當前BeanDefinition表示的bean是否是一個抽象類,但是前面已經檢查過了 這裡再次檢查貌似意義不大
            checkMergedBeanDefinition(mbd, beanName, args);
            
            //檢查是否配置了bean的依賴 如果存在則需要先例項化被依賴的bean
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dependsOnBean : dependsOn) {
                    if (isDependent(beanName, dependsOnBean)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                    }
                    registerDependentBean(dependsOnBean, beanName);
                    getBean(dependsOnBean);
                }
            }

            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }else if (mbd.isPrototype()) {
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; " +
                            "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
        try {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }catch (TypeMismatchException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to convert bean '" + name + "' to required type [" +
                        ClassUtils.getQualifiedName(requiredType) + "]", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}
方法中的try-catch塊用於建立bean例項,程式碼很多,不過只是根據bean的作用範圍來進行建立如Singleton,prototype或者session等。建立bean的過程大同小異,區別僅在與例項儲存的地方。單例bean被儲存在一個map中,整個程式執行期間有效。原型bean儲存在另外的容器中,每一次使用時需要重新建立。

以單例bean建立過程為例,主要實現過程都在```getSingleton(...)```方法中了。```getSingleton(...)```的主要功能就是檢查bean是否已經建立,如果沒建立就進行建立然後儲存到容器中。建立bean的過程由一個匿名內部類實現。

#### createBean(String beanName, RootBeanDefinition mbd, Object[] args)
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    resolveBeanClass(mbd, beanName);
    try {
        mbd.prepareMethodOverrides();
    }catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        //首先嚐試執行BeanPostProcessor,如果存在後置處理器 那麼首先例項化bean執行處理器
        Object bean = resolveBeforeInstantiation(beanName, mbd);
        if (bean != null) {
            return bean;
        }
    }catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }
    //不存在後置處理器或者存在的執行處理器過程建立例項失敗或沒有建立例項的動作則執行下面的方法
    Object beanInstance = doCreateBean(beanName, mbd, args);
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
}
上面方法中有這樣一句```mbd.prepareMethodOverrides()```。```methodOverrides```實際上市BeanDefinition中的一個屬性。其主要用於記錄在配置檔案中lookup-method和replaced-method引數設定的值。詳情可以看這裡:[methodOverrides](https://blog.csdn.net/G0_hw/article/details/82149000)

#### doCreateBean(...)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        //如果已經例項化需要重新例項化則從快取中刪除 重新設定
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    //more code
}

方法開頭顯示建立了一個BeanWrapper的物件,BeanWrapper相當於一個代理器,Spring委託BeanWrapper來完成bean內部屬性的初始化。

上述方法程式碼很多,在建立階段只需要關注前幾行。如果該bean的例項未被建立則直接建立一個。建立的方法有createBeanInstance完成。

#### createBeanInstance(...)
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    //判斷當前bean類是否被定義為public 非public的類無法在其他類中例項化
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
    if (mbd.getFactoryMethodName() != null)  {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            return instantiateBean(beanName, mbd);
        }
    }

    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    return instantiateBean(beanName, mbd);
}

該方法先是嘗試檢視是否配置了工廠方法,如果存在工廠方法則由工廠方法進行建立。

接下來的幾行程式碼是用來提升效能的。spring在建立例項後會將建立該例項的constructor方法快取,這樣下一次需要建立該bean時直接取出構造方法建立即可不需要再重新解析一次。

如果沒有工廠方法並且構造方法也沒有快取,同時沒有找到有參的建構函式,那麼會通過放射呼叫類的預設無參建構函式。

#### instantiateBean(String, RootBeanDefinition)

該例項化方法沒有太多解析的必要,基本就是通過反射的原理獲取無參建構函式,通過建構函式來例項化類。

### DI
到這裡為止建立一個例項的過程就完成了,接下來就是檢查該例項是否需要被注入其他的屬性了。

#### 回到doCreateBean(...)
前面在建立bean例項時呼叫到了doCreateBean(...)方法,在建立好例項後的後續功能也依賴於該方法。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
    // other-code
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    } catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }else {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }
    // other-code
    return exposedObject;
}
在DI階段我們需要關注的就上上面的程式碼,首先是通過populateBean方法對在配置檔案中配置的property屬性進行設定值。

populateBean顧名思義就是對bean中的屬性新增資料。populateBean中其實是通過後置處理器來進行屬性的設定,主要的程式碼如下:

PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}

spring中預設註冊了以下幾種beanPostProcessor,如下:

![beanPostProcessor](https://user-gold-cdn.xitu.io/2019/6/22/16b7cfcd1669ee2a?w=695&h=426&f=png&s=32220)

每一個beanPostProcessor都會在例項化前後相應的地方進行呼叫。在這裡我們需要關注的是```AutowiredAnnotationBeanPostProcessor```,```RequiredAnnotationBeanPostProcessor```,```CommonAnnotationBeanPostProcessor```這幾個註解。

顧名思義這幾個beanPostProcessor都是用來處理註解的,對應用來處理```@Autowired```,```@Required```,```@Common```幾個註解。

這裡以```@Autowored```的處理為例。

#### AutowiredAnnotationBeanPostProcessor
public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass());
    try {
        metadata.inject(bean, beanName, pvs);
    }catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
    Class<?> targetClass = clazz;

    do {
        LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
        for (Field field : targetClass.getDeclaredFields()) {
            AnnotationAttributes annotation = findAutowiredAnnotation(field);
            if (annotation != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation is not supported on static fields: " + field);
                    }
                    continue;
                }
                boolean required = determineRequiredStatus(annotation);
                currElements.add(new AutowiredFieldElement(field, required));
            }
        }
        for (Method method : targetClass.getDeclaredMethods()) {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                continue;
            }
            AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation is not supported on static methods: " + method);
                    }
                    continue;
                }
                if (method.getParameterTypes().length == 0) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation should be used on methods with actual parameters: " + method);
                    }
                }
                boolean required = determineRequiredStatus(ann);
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        }
        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
}

該方法主要就是通過解析當前bean有哪些屬性被```@Autowired```註解修飾,將其封裝為一個```InjectionMetadata```物件。解析的過程通過```findAutowiringMetadata(String beanName, Class<?> clazz)```完成,但實際上主要還是通過上面的```buildAutowiringMetadata(Class<?> clazz)```完成。

方法比較簡單,首先就是遍歷bean的所有欄位(Field),通過反射的方法查詢欄位上的註解,如果存在匹配的註解(```AutowiredAnnotationBeanPostProcessor```匹配的就是```@Autowired```)。如果存在該註解就將這個欄位記錄表示需要進行注入。

當將欄位遍歷完成後就取出所有的方法,查詢方法上是否有該註解,如果存在的話同理記錄下該方法。

對於被記錄下的欄位或者方法會被封裝成一個```InjectedElement```物件。通過該物件的inject方法完成注入工作。

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
try {
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
} else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set

剛方法總體來說比較簡單,首先是查詢當前bean的依賴是否已經被快取,如果快取了則從快取中取即可。

如果是第一次解析則從beanfactory中獲取相應的依賴屬性。

synchronized程式碼塊主要就是將解析後的依賴的值快取起來,建立當前bean和其依賴的屬性之間的關係。當下一次建立該型別的bean時可以直接使用不需重新解析。

而真正的屬性注入是依賴著幾行程式碼:

if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
```

上面的程式碼沒有任何的難度,就是對JDK中反射的api的使用。

基本上後面就是重複這個過程對bean的屬性進行注入,在這一過程中最重要的就是beanPostProcessor,注入都已依賴這一組完成的