SpringIOC中bean的生命周期

  • 定義
    bean的生命周期指的是在Spring中IOC容器從初始化到銷毀這一整個(gè)全過程宪迟。同時(shí)在這一過程里關(guān)系到各個(gè)級別的接口的作用和自定義實(shí)現(xiàn)。

先簡單說一下bean的整個(gè)生命周期:創(chuàng)建(實(shí)例化、屬性賦值、初始化)驮履、使用、銷毀苗桂。而spring提供了一些接口允許在這個(gè)過程中進(jìn)行一定程度的擴(kuò)展。

  • 各個(gè)級別的接口
  1. 工廠后處理器接口方法:諸如BeanFactoryPostProcessor告组,CustomAutowireConfigure等煤伟,它們是在容器裝置配置文件之后調(diào)用,可以說是最先調(diào)用的方法了木缝。
  2. 容器級生命周期接口方法:InstantiationAwareBeanPostProcessor(繼承自BeanPostProcessor) 和BeanPostProcessor 這兩個(gè)的接口的實(shí)現(xiàn)便锨。我們一般稱之為后置處理器
  3. Bean級別生命周期接口:BeanNameAware,BeanFactoryAware我碟,IntializaingBean放案,DiposableBean 這些接口的方法。每個(gè)Bean都可以選擇實(shí)現(xiàn)矫俺,可以選擇各自的自定義操作
  4. Bean自身的方法:init-method / destory-method 吱殉, 通過在配置文件bean定義的相應(yīng)屬性中掸冤,指定相應(yīng)的執(zhí)行方法。

現(xiàn)在我們具體的來說一下整個(gè)生命周期以及相關(guān)的接口的方法執(zhí)行的時(shí)機(jī):
直接上一段代碼:

package com.suxin;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

//DDDbean繼承自BeanFactoryPostProcessor 是一個(gè)工廠后置處理器
public class DDDbean implements BeanFactoryPostProcessor {


    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("DDDbean...BeanFactoryPostProcessor.postProcessBeanFactory 執(zhí)行中...");
    }


    public DDDbean() {
        System.out.println("DDDbean.構(gòu)造方法 執(zhí)行中...");
    }
}

package com.suxin;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

import java.beans.PropertyDescriptor;
//EEEbean實(shí)現(xiàn)了InstantiationAwareBeanPostProcessor 接口(該接口是一個(gè)容器級別的生命周期的接口方法)
public class EEEbean implements InstantiationAwareBeanPostProcessor {

    private String name;

    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 執(zhí)行中...");
        return null;
    }

    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 執(zhí)行中...");

        return true;
    }

    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessPropertyValues 執(zhí)行中...");
        return pvs;
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 執(zhí)行中...");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInitialization 執(zhí)行中...");
        return bean;
    }

    public EEEbean() {
        System.out.println("EEEbean.構(gòu)造方法 執(zhí)行中...");
    }

    public String getName() {
        System.out.println("EEEbean.getName 執(zhí)行中...");
        return name;
    }

    public void setName(String name) {
        System.out.println("EEEbean.setName 執(zhí)行中...");
        this.name = name;
    }
}

package com.suxin;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

//FFFbean實(shí)現(xiàn)了BeanNameAware考婴、BeanFactoryAware贩虾、IntializaingBean催烘、DiposableBean 這四種bean級別的生命周期接口方法
//同時(shí)也寫了initMethod和destroyMethod倆種方法即將裝配到xml的bean配置里的init-method和destroy-method屬性
public class FFFbean implements BeanNameAware, BeanFactoryAware, InitializingBean,DisposableBean {

    private String value;

    public void setBeanName(String name) {
        System.out.println("FFFbean.setBeanName 執(zhí)行中..."+name);
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("FFFbean.setBeanFactory 執(zhí)行中...");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("FFFbean.afterPropertiesSet 執(zhí)行中...");
    }

    public void destroy() throws Exception {
        System.out.println("FFFbean.destroy 執(zhí)行中...");
    }


    public FFFbean() {
        System.out.println("FFFbean.構(gòu)造方法 執(zhí)行中...");
    }

    public void doSomething() {
        System.out.println("doSomething...");
    }


    public String getValue() {
        System.out.println("FFFbean.getValue 執(zhí)行中... " + value);
        return value;
    }

    public void setValue(String value) {
        System.out.println("FFFbean.setValue 執(zhí)行中... " + value);
        this.value = value;
    }

    public void initMethod() {
        System.out.println("FFFbean.initMethod...");
    }

    public void destroyMethod() {
        System.out.println("FFFbean.destroyMethod...");
    }
}

xml配置相關(guān):

<bean id="dDDbean" class="com.suxin.DDDbean"></bean>
<bean id="eEEbean" class="com.suxin.EEEbean">
    <property name="name" value="lalala"></property>
</bean>
<bean id="fFFbean" class="com.suxin.FFFbean" init-method="initMethod" destroy-method="destroyMethod">
    <property name="value" value="jiujiu"></property>
</bean>

運(yùn)行main方法

public class App {
    public static void main( String[] args ) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        FFFbean fFFbean= (FFFbean)context.getBean("fFFbean");
        fFFbean.doSomething();
//        context.getAutowireCapableBeanFactory().destroyBean(fFFbean);

        context.close();

執(zhí)行結(jié)果

八月 10, 2019 1:43:17 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2e0fa5d3: startup date [Sat Aug 10 13:43:17 CST 2019]; root of context hierarchy
八月 10, 2019 1:43:17 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
DDDbean.構(gòu)造方法 執(zhí)行中...
DDDbean...BeanFactoryPostProcessor.postProcessBeanFactory 執(zhí)行中...
EEEbean.構(gòu)造方法 執(zhí)行中...
EEEbean.setName 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 執(zhí)行中...
FFFbean.構(gòu)造方法 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessPropertyValues 執(zhí)行中...
FFFbean.setValue 執(zhí)行中... jiujiu
FFFbean.setBeanName 執(zhí)行中...fFFbean
FFFbean.setBeanFactory 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 執(zhí)行中...
FFFbean.afterPropertiesSet 執(zhí)行中...
FFFbean.initMethod...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInitialization 執(zhí)行中...
doSomething...
八月 10, 2019 1:43:19 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@2e0fa5d3: startup date [Sat Aug 10 13:43:17 CST 2019]; root of context hierarchy
FFFbean.destroy 執(zhí)行中...
FFFbean.destroyMethod...

Process finished with exit code 0

ok沥阱,代碼相關(guān)已經(jīng)貼完,我們開始來解釋一下伊群。當(dāng)然以上代碼如果感興趣可以直接復(fù)制下來考杉,自己運(yùn)行一遍,加深印象舰始。

貼一段AbstractApplicationContext的refresh方法的源碼崇棠,我會(huì)忽略一些不是本章關(guān)注的代碼

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            // ...

            // Tell the subclass to refresh the internal bean factory.
            // ...

            // Prepare the bean factory for use in this context.
            // ...

            try {
                // 讓繼承容器的子類容器進(jìn)行擴(kuò)展的
                postProcessBeanFactory(beanFactory);

                // 創(chuàng)建BeanFactoryPostProcessor實(shí)例,并且調(diào)用相關(guān)方法丸卷,也就是在這個(gè)方法里DDDbean會(huì)被初始化枕稀,且會(huì)被調(diào)用相關(guān)方法
                invokeBeanFactoryPostProcessors(beanFactory);

                // 初始化實(shí)現(xiàn)了BeanPostProcessor 和 InstantiationAwareBeanPostProcessor接口方法的bean,也就是說這里EEEbean被初始化 ps:還未調(diào)用相關(guān)方法
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                // ...

                // Initialize event multicaster for this context.
                // ...

                // Initialize other special beans in specific context subclasses.
                // ...

                // Check for listener beans and register them.
                // ...

                // 完成初始化的工作谜嫉,等會(huì)會(huì)深入進(jìn)入看看
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                // ...
            }

            catch (BeansException ex) {
                // ...

                // Destroy already created singletons to avoid dangling resources.
                // ...

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // 重置Spring核心中常見的默認(rèn)緩存萎坷,因?yàn)槲覀?                // 可能不再需要用于單例bean的元數(shù)據(jù)了…
                resetCommonCaches();
            }
        }
    }

首先是DDDbean的構(gòu)造方法被執(zhí)行了,然后繼續(xù)執(zhí)行這個(gè)bean的實(shí)現(xiàn)了BeanFactoryPostProcessor的postProcessBeanFactory方法沐兰。ok第一步已經(jīng)出來了BeanFactoryPostProcessor這種級別的bean會(huì)被首先初始化然后緊接著就是調(diào)用該bean的postProcessBeanFactory方法哆档。
其發(fā)生的時(shí)機(jī)就是在AbstractApplicationContext的refresh方法里的調(diào)用invokeBeanFactoryPostProcessors方法
貼一段invokeBeanFactoryPostProcessors的源碼(已經(jīng)刪除非重點(diǎn)代碼):

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }
//繼續(xù)看代碼
//PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
//這是個(gè)靜態(tài)方法,由于代碼很多我就忽略了非本章關(guān)注的代碼
public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<String>();

        // ......

        // 獲取到所有工廠后處理器接口實(shí)現(xiàn)類的名字,DDDbean的名字就包含在里面
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // 為容器內(nèi)的BeanFactoryPostProcessor規(guī)定創(chuàng)建順序和執(zhí)行方法的順序
        // 優(yōu)先級最高的是priorityOrdered住闯,其次是ordered瓜浸,最后的是nonOrdered
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        List<String> orderedPostProcessorNames = new ArrayList<String>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        // ...... 

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        // ......

        // 關(guān)注這個(gè)部分,DDDbean即將在這里被初始化然后調(diào)用它的方法
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // 清除緩存的合并bean定義比原,因?yàn)楹筇幚砥骺赡?        // 修改了原始元數(shù)據(jù)插佛,例如替換值中的占位符…
        beanFactory.clearMetadataCache();
    }

通過源碼解讀,我們可以了解到為什么DDDbean會(huì)優(yōu)先被初始化且被調(diào)用實(shí)現(xiàn)的postProcessBeanFactory方法量窘。
接下來我們繼續(xù)看到EEEbean被初始化(實(shí)例化+屬性賦值)朗涩,且相對于FFFbean來說是優(yōu)先初始化。繼續(xù)看源碼绑改,這一次我們深入到registerBeanPostProcessors(beanFactory)方法里去看谢床。非本章關(guān)注代碼已經(jīng)忽略

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

//繼續(xù)深入進(jìn)去看 省略無關(guān)代碼
public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
        // 獲取到了EEEbean的名字放在了postProcessorNames 數(shù)組里面
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        // ......

        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
        List<String> orderedPostProcessorNames = new ArrayList<String>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                //關(guān)注一下這個(gè)方法 EEEbean的名字被放到這個(gè)集合里面
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, register the BeanPostProcessors that implement PriorityOrdered.
        // ......

        // Next, register the BeanPostProcessors that implement Ordered.
        // ......

        // Now, register all regular BeanPostProcessors.
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
        for (String ppName : nonOrderedPostProcessorNames) {
            // 關(guān)注點(diǎn)在這里,初始化BeanPostProcessor相關(guān)類 也就是EEEbean在這里進(jìn)行初始化(實(shí)例化+屬性賦值)
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // Finally, re-register all internal BeanPostProcessors.
        // ......

        // Re-register post-processor for detecting inner beans as ApplicationListeners,
        // moving it to the end of the processor chain (for picking up proxies etc).
        // ......
    }

OK通過上面的源碼解釋了為什么EEEbean先FFFbean一步進(jìn)行初始化了厘线。
繼續(xù)看源碼refresh方法里finishBeanFactoryInitialization(beanFactory)的方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        // ... ...

        // Register a default embedded value resolver if no bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.
        // ......

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        // ......

        // Stop using the temporary ClassLoader for type matching.
        // ......

        // Allow for caching all bean definition metadata, not expecting further changes.
        // ......

        // 重點(diǎn)關(guān)注方法
        beanFactory.preInstantiateSingletons();
    }

繼續(xù)看beanFactory.preInstantiateSingletons();

public void preInstantiateSingletons() throws BeansException {
        // ......

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    // ......
                }
                else {
                    //重點(diǎn)方法 關(guān)注一波
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        // ......
    }

繼續(xù)看getBean方法识腿,其實(shí)就是看doGetBean方法(繼續(xù)省略不是本章關(guān)注重點(diǎn)的代碼):

protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

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

        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            // ......
        }

        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            // ......

            // Check if bean definition exists in this factory.
            // ......

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

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

                // Guarantee initialization of beans that the current bean depends on.
                // ......

                // 關(guān)注單例的bean的創(chuàng)建 重點(diǎn)關(guān)注createBean方法
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                // 重點(diǎn)就這個(gè)方法里
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    // ......
                }

                else {
                    // ......
                    catch (IllegalStateException ex) {
                        // ......
                    }
                }
            }
            catch (BeansException ex) {
                // ......
            }
        }

        // Check if required type matches the type of the actual bean instance.
        // ......
        return (T) bean;
    }

繼續(xù)看createBean的方法(同樣還是忽略不必要的代碼)

@Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        // ......
        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.
        // ......

        // Prepare method overrides.
        // ......

        try {
            // 首先關(guān)注這個(gè)方法
            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);
        }
        //docreateBean的方法依然是我們關(guān)注的重點(diǎn)。
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        // ......
        return beanInstance;
    }

ok造壮,通過上面的代碼我們已經(jīng)提煉處我們需要關(guān)注的倆個(gè)方法:resolveBeforeInstantiation(beanName, mbdToUse)和doCreateBean(beanName, mbdToUse, args)渡讼,ok我們一個(gè)個(gè)來看:
首先是resolveBeforeInstantiation的源碼:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    //就是這里會(huì)調(diào)用一次EEEbean的postProcessBeforeInstantiation方法骂束,
                    // 具體的方法大家進(jìn)去看一下非常簡單。
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

上面的代碼說明了EEEbean會(huì)被調(diào)用實(shí)現(xiàn)的postProcessBeforeInstantiation方法成箫,同時(shí)因?yàn)樵摲椒ㄔ贓EEbean的實(shí)現(xiàn)里返回的是一個(gè)null展箱,所以不會(huì)立即執(zhí)行EEEbean的postProcessAfterInstantiation方法,會(huì)放在后面來執(zhí)行蹬昌。(對了此時(shí)我們得明白一下現(xiàn)在的情況混驰,DDDbean和EEEbean已經(jīng)被初始化了,但是FFFbean還沒有完成初始化(按照目前的這個(gè)代碼進(jìn)度來說FFFbean的實(shí)例化還未完成))
繼續(xù),我們來看doCreateBean方法代碼

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

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //關(guān)注一下這里皂贩,在這里會(huì)完成FFFbean的實(shí)例化栖榨,也就是FFFbean的構(gòu)造方法會(huì)被調(diào)用
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        mbd.resolvedTargetType = beanType;

        // Allow post-processors to modify the merged bean definition.
        // ......

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        // ......

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            // 關(guān)注這個(gè)方法,會(huì)完成FFFbean的屬性注入
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                // 關(guān)注這個(gè)方法明刷,完成bean的相關(guān)實(shí)現(xiàn)方法的回調(diào)
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
        catch (Throwable ex) {
            // ......
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

通過上面的源碼我們可以看到主要有三個(gè)方法值得關(guān)注createBeanInstance婴栽、populateBean、initializeBean辈末。createBeanInstance完成了FFFbean的實(shí)例化(也就是調(diào)用了FFFbean的構(gòu)造方法)
我們來重點(diǎn)關(guān)注一下populateBean方法

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();

        // ......

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    //關(guān)注這里愚争,解釋了為什么EEEbean執(zhí)行了postProcessAfterInstantiation方法
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

        // ......

        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()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        //關(guān)注一下這里,會(huì)執(zhí)行EEEbean的postProcessPropertyValues方法
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
        //執(zhí)行FFFbean的賦值操作挤聘,F(xiàn)FFbean的setValue方法
        applyPropertyValues(beanName, mbd, bw, pvs);
    }

以上轰枝,populateBean方法解釋完了,DDDbean和EEEbean都已經(jīng)被初始化了而FFFbean已經(jīng)完成了實(shí)例化和屬性注值檬洞,現(xiàn)在就差FFFbean的實(shí)現(xiàn)相關(guān)接口的方法回調(diào)了狸膏。我們繼續(xù)看initializeBean方法。

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 {
            //重點(diǎn)關(guān)注一下這個(gè)方法添怔,回調(diào)了FFFbean實(shí)現(xiàn)了
            //BeanNameAware和BeanFactoryAware接口的方法,具體的
            //大家點(diǎn)擊進(jìn)去看一下湾戳,代碼很簡單
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //關(guān)注重點(diǎn) 此方法里回調(diào)了EEEbean的postProcessBeforeInitialization方法,大家可以自己點(diǎn)進(jìn)去广料,非常簡單明了
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            //關(guān)注重點(diǎn) 在這個(gè)方法里主要執(zhí)行了FFFbean實(shí)現(xiàn)了InitializingBean接口的方法和自身initMethod屬性的方法砾脑。
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            //關(guān)注重點(diǎn)  此方法里回調(diào)了EEEbean的postProcessAfterInitialization方法,大家可以自己點(diǎn)進(jìn)去艾杏,非常簡單明了
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

至此韧衣,F(xiàn)FFbean完成了初始化的所有工作(實(shí)例化+屬性注入+接口方法回調(diào)),而且整個(gè)控制臺(tái)打印的東西里doSomething之前的打印部分已經(jīng)解釋完畢购桑。我們現(xiàn)在再把整個(gè)空調(diào)臺(tái)打印的東西展示一下畅铭,防止大家忘記:

八月 10, 2019 1:43:17 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2e0fa5d3: startup date [Sat Aug 10 13:43:17 CST 2019]; root of context hierarchy
八月 10, 2019 1:43:17 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
DDDbean.構(gòu)造方法 執(zhí)行中...
DDDbean...BeanFactoryPostProcessor.postProcessBeanFactory 執(zhí)行中...
EEEbean.構(gòu)造方法 執(zhí)行中...
EEEbean.setName 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 執(zhí)行中...
FFFbean.構(gòu)造方法 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessPropertyValues 執(zhí)行中...
FFFbean.setValue 執(zhí)行中... jiujiu
FFFbean.setBeanName 執(zhí)行中...fFFbean
FFFbean.setBeanFactory 執(zhí)行中...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 執(zhí)行中...
FFFbean.afterPropertiesSet 執(zhí)行中...
FFFbean.initMethod...
EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInitialization 執(zhí)行中...
doSomething...
八月 10, 2019 1:43:19 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@2e0fa5d3: startup date [Sat Aug 10 13:43:17 CST 2019]; root of context hierarchy
FFFbean.destroy 執(zhí)行中...
FFFbean.destroyMethod...

Process finished with exit code 0

接著我們把main方法的代碼再次展示一下:

public class App {
    public static void main( String[] args ) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        FFFbean fFFbean= (FFFbean)context.getBean("fFFbean");
        fFFbean.doSomething();
//        context.getAutowireCapableBeanFactory().destroyBean(fFFbean);

        context.close();

ok,fffbean對象執(zhí)行了doSomething方法勃蜘。緊接著就是容器的關(guān)閉硕噩。

在容器關(guān)閉的方法里,會(huì)先調(diào)用FFFbean實(shí)現(xiàn)DisposableBean的destroy方法缭贡,然后再接著調(diào)用FFFbean本身的destoryMethod屬性里的方法
具體的感興趣的可以自己看源碼一步步的debug炉擅。

跟著源碼走一遍辉懒,估計(jì)大家這會(huì)都有點(diǎn)暈乎了,我們來做一些總結(jié)吧:
首先Spring的bean的生命周期只有五步:實(shí)例化谍失、屬性賦值眶俩、初始化、使用快鱼、銷毀颠印。

實(shí)例化、屬性賦值攒巍、初始化分別對應(yīng)三個(gè)方法嗽仪,都是在doCreateBean方法里面荒勇,也就是createBeanInstance柒莉、populateBean、initializeBean沽翔。

說完了bean的生命周期兢孝,我們來說一下各個(gè)接口的方法調(diào)用的時(shí)機(jī)。
BeanFactoryPostProcessor類型的接口bean是最先被創(chuàng)建(實(shí)例化仅偎、屬性注入跨蟹、初始化)并且被調(diào)用的postProcessBeanFactory方法的。該時(shí)機(jī)是refresh方法里的invokeBeanFactoryPostProcessors方法里橘沥。refresh的registerBeanPostProcessors方法里主要是做了BeanPostProcessor類型(包括InstantiationAwareBeanPostProcessor)的創(chuàng)建(實(shí)例化窗轩、屬性注入、初始化)座咆,而InstantiationAwareBeanPostProcessor類型的方法調(diào)用的時(shí)機(jī)是在doCreateBean里痢艺。

InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法會(huì)在createBeanInstance(實(shí)例化)之前調(diào)用,而它的postProcessAfterInstantiation方法則會(huì)在createBeanInstance(實(shí)例化)之后調(diào)用介陶。在populateBean(屬性注入)方法里會(huì)調(diào)用它的postProcessPropertyValues堤舒。

接下來就是各種bean級別的生命周期接口諸如beanNameAware、BeanFactoryAware都會(huì)在initializeBean(初始化方法里)里面首先調(diào)用哺呜,然后調(diào)用的是BeanPostProcessor接口的postProcessBeforeInitialization方法舌缤,后面接著就是InitializingBean接口的afterPropertiesSet方法,最后再次調(diào)用BeanPostProcessor接口的postProcessAfterInitialization方法某残。

說完了創(chuàng)建階段国撵,再說一下銷毀階段,銷毀階段就是先調(diào)用DisposableBean接口的destroy方法玻墅,然后再調(diào)用bean自身的destroyMethod關(guān)聯(lián)的方法介牙。

至此整個(gè)bean的生命周期和接口方法的擴(kuò)展時(shí)機(jī)我們就說完了,可能有點(diǎn)多有點(diǎn)雜椭豫,大家多看看耻瑟,最好能根據(jù)我的代碼自己跑一遍debug一遍旨指,相信就會(huì)了解的更加深刻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喳整,一起剝皮案震驚了整個(gè)濱河市谆构,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌框都,老刑警劉巖搬素,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異魏保,居然都是意外死亡熬尺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門谓罗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粱哼,“玉大人,你說我怎么就攤上這事檩咱〗掖耄” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵刻蚯,是天一觀的道長绊含。 經(jīng)常有香客問我,道長炊汹,這世上最難降的妖魔是什么躬充? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮讨便,結(jié)果婚禮上充甚,老公的妹妹穿的比我還像新娘。我一直安慰自己器钟,他們只是感情好津坑,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著傲霸,像睡著了一般疆瑰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昙啄,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天穆役,我揣著相機(jī)與錄音,去河邊找鬼梳凛。 笑死耿币,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的韧拒。 我是一名探鬼主播淹接,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼十性,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了塑悼?” 一聲冷哼從身側(cè)響起劲适,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厢蒜,沒想到半個(gè)月后霞势,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斑鸦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年愕贡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巷屿。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡固以,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出攒庵,到底是詐尸還是另有隱情嘴纺,我是刑警寧澤败晴,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布浓冒,位于F島的核電站,受9級特大地震影響尖坤,放射性物質(zhì)發(fā)生泄漏稳懒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一慢味、第九天 我趴在偏房一處隱蔽的房頂上張望场梆。 院中可真熱鬧,春花似錦纯路、人聲如沸或油。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顶岸。三九已至,卻和暖如春叫编,著一層夾襖步出監(jiān)牢的瞬間辖佣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工搓逾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卷谈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓霞篡,卻偏偏與公主長得像世蔗,于是被迫代替她去往敵國和親端逼。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容