1. 程式人生 > 實用技巧 >Spring原始碼解析(四) -- getBean(String name, Class<T> requiredType)

Spring原始碼解析(四) -- getBean(String name, Class<T> requiredType)

前言

  早在分析beanFactoryPostProcessor的時候,就出現了BeanFactory.getBean方法,因為每一個beanFactoryPostProcessor也是spring管理的bean,也是要經過spring例項化和初始化才能夠使用的,只是當時該方法還不是要分析的重點。

1 查詢快取

  

final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
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); }

這部分是先查詢該bean是否在之前有過快取,有就直接使用了,還有一種情況是該bean是一個beanFactory那麼就呼叫beanFactory的getObject方法

2 從父容器中初始化bean

  

// Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

程式碼的作用比較清晰

3 開始例項化

try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        getBean(dep);
                    }
                }

  注意這裡的mergedBeanDefinition,根據文件beanDefinition也是有繼承關係的。注意不是真的類的繼承關係,我寫的程式碼測試B繼承A,但是還是兩個BeanDefinition。

  

mergedBeanDefinitions 是在 AbstractBeanFactory裡的
private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
            new ConcurrentHashMap<String, RootBeanDefinition>(256);

  而儲存所有的beanDefinition是在DefaultListableBeanFactory的

/** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

  總之一句話,一個beanDefinition會經過轉換變成mergedBeanDefinition,儘管大多數的beanDefinition還是保持著原樣。而接下來的例項化一個bean就是使用mergedBeanDefinition。

  這裡做的第二件事是例項化該bean所依賴的bean。注意這裡的dependon並不是指@Autowired這種依賴注入,而是大概這種方式

  

<bean id="cat" class="com.lyc.cn.day08.Cat" p:name="美美" depends-on="dog"/>

  同樣的上面說的mergedBeanDefinition也不是指兩個類之間的繼承關係,而是這種通過配置檔案配出來的兩個bean的關係

<bean id="parentBean" abstract="true">
        <property name="name" value="我是父親"/>
    </bean>
    <bean id="sunBean" class="com.lyc.cn.day08.SunBean" parent="parentBean">
        <property name="age" value="18"/>
    </bean>

  接下來就是正式的例項化過程了

4AbstractAutowireCapableBeanFactory.createBean

  第一部分

  

  if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

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

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

  特別注意,// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. spring的動態代理就是在這裡被執行的。

  第二部分

  AbstractAutowireCapableBeanFactory.doCreateBean

  

// Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }

真正進行例項化的程式碼就在createBeanInstance 裡,

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 對於絕大部分bean來說都是通過反射,利用class拿到構造方法,再用構造方法例項化物件,這裡不再展開。

  回到doCreateBean繼續分析

  快取需要依賴注入的元資訊

// Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

  applyMergedBeanDefinitionPostProcessors 的是就是這樣的,那麼MergedBeanDefinitionPostProcessor的實現類有哪些呢?還真有一個比較有名的AutowiredAnnotationBeanPostProcessor。AutowiredAnnotationBeanPostProcessor是能夠處理@Autowired和@Value這樣的註解的

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof MergedBeanDefinitionPostProcessor) {
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }

  我們來看看AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition幹了啥。

@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanType != null) {
            InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
            metadata.checkConfigMembers(beanDefinition);
        }
    }
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
        // Fall back to class name as cache key, for backwards compatibility with custom callers.
        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
        // Quick check on the concurrent map first, with minimal locking.
        InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized (this.injectionMetadataCache) {
                metadata = this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
                    try {
                        metadata = buildAutowiringMetadata(clazz);
                        this.injectionMetadataCache.put(cacheKey, metadata);
                    }
findAutowiringMetadata方法是很長的,這裡只擷取一段程式碼看看意思。
buildAutowiringMetadata構造出來一個要注入的元資料物件,同時快取在 injectionMetadataCache裡面,快取的key就是
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
InjectionMetadata 是什麼呢,就是一個物件裡哪個屬性是需要注入的(其他的由spring管理的物件,而不是基本型別)。
這些快取資訊AutowiredAnnotationBeanPostProcessor在後續程式碼執行中會用到的。

  再次回到doCreateBean繼續分析

  解決迴圈依賴的

// Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

  解決迴圈依賴的

  屬性注入及初始化

  最重要的兩個方法,populateBean和initializeBean

  populateBean是解決一個bean屬性初始值的

  initializeBean是呼叫初始化方法的,比如@PostConstruct,配置檔案裡的init-method,和實現了InitializingBean介面的介面方法

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);
            }
        }

  分析下populateBean

if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }
     //上面的程式碼現在幾乎不會走到,都是為了相容老程式碼的,而且像@Autowired等註解也不走到裡面
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {//迴圈遍歷每一個beanPostProcessor呼叫他們的postProcessPropertyValues
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }

  不妨我們還是以AutowiredAnnotationBeanPostProcessor的 方法來舉例

  

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

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

之前在快取需要依賴注入的元資訊 這個小節交代過了, 例項化後會處理一個bean中的標籤@Autowired並快取起來。

現在就可以直接用了

拿到InjectionMetadata metadata 後就呼叫inject。

對於autowired來說他對應的 方法是這樣的

  

@Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            Object value;
            if (this.cached) {
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            }
            else {
                DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                desc.setContainingClass(bean.getClass());
                Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
                TypeConverter typeConverter = beanFactory.getTypeConverter();
                try {
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);//把依賴的值解析出來
                }
                catch (BeansException ex) {
                    throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
                }
                synchronized (this) {
                    if (!this.cached) {
                        if (value != null || this.required) {
                            this.cachedFieldValue = desc;
                            registerDependentBeans(beanName, autowiredBeanNames);
                            if (autowiredBeanNames.size() == 1) {
                                String autowiredBeanName = autowiredBeanNames.iterator().next();
                                if (beanFactory.containsBean(autowiredBeanName)) {
                                    if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                        this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                                desc, autowiredBeanName, field.getType());
                                    }
                                }
                            }
                        }
                        else {
                            this.cachedFieldValue = null;
                        }
                        this.cached = true;
                    }
                }
            }
            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);//反射方法直接塞進去
            }
        }

  initializeBean

  到了執行初始化方法的時候了,這裡說的初始化有三種,@PostConstruct,bean實現了initializingBean介面,和配置了init-method方法,這三種情況的執行。

  先看程式碼

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//就在這裡執行的@PostConstruct
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);//先initializingBean介面,而後才是init-method方法
}
catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//大多數後置處理器都是直接return原bean } return wrappedBean; }