美文网首页
SpringIOC中bean的生命周期

SpringIOC中bean的生命周期

作者: 耐得千事烦 | 来源:发表于2019-08-12 16:27 被阅读0次
    • 定义
      bean的生命周期指的是在Spring中IOC容器从初始化到销毁这一整个全过程。同时在这一过程里关系到各个级别的接口的作用和自定义实现。

    先简单说一下bean的整个生命周期:创建(实例化、属性赋值、初始化)、使用、销毁。而spring提供了一些接口允许在这个过程中进行一定程度的扩展。

    • 各个级别的接口
    1. 工厂后处理器接口方法:诸如BeanFactoryPostProcessor,CustomAutowireConfigure等,它们是在容器装置配置文件之后调用,可以说是最先调用的方法了。
    2. 容器级生命周期接口方法:InstantiationAwareBeanPostProcessor(继承自BeanPostProcessor) 和BeanPostProcessor 这两个的接口的实现。我们一般称之为后置处理器
    3. Bean级别生命周期接口:BeanNameAware,BeanFactoryAware,IntializaingBean,DiposableBean 这些接口的方法。每个Bean都可以选择实现,可以选择各自的自定义操作
    4. Bean自身的方法:init-method / destory-method , 通过在配置文件bean定义的相应属性中,指定相应的执行方法。

    现在我们具体的来说一下整个生命周期以及相关的接口的方法执行的时机:
    直接上一段代码:

    package com.suxin;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    
    //DDDbean继承自BeanFactoryPostProcessor 是一个工厂后置处理器
    public class DDDbean implements BeanFactoryPostProcessor {
    
    
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("DDDbean...BeanFactoryPostProcessor.postProcessBeanFactory 执行中...");
        }
    
    
        public DDDbean() {
            System.out.println("DDDbean.构造方法 执行中...");
        }
    }
    
    
    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实现了InstantiationAwareBeanPostProcessor 接口(该接口是一个容器级别的生命周期的接口方法)
    public class EEEbean implements InstantiationAwareBeanPostProcessor {
    
        private String name;
    
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 执行中...");
            return null;
        }
    
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 执行中...");
    
            return true;
        }
    
        public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
            System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessPropertyValues 执行中...");
            return pvs;
        }
    
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 执行中...");
            return bean;
        }
    
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInitialization 执行中...");
            return bean;
        }
    
        public EEEbean() {
            System.out.println("EEEbean.构造方法 执行中...");
        }
    
        public String getName() {
            System.out.println("EEEbean.getName 执行中...");
            return name;
        }
    
        public void setName(String name) {
            System.out.println("EEEbean.setName 执行中...");
            this.name = name;
        }
    }
    
    
    package com.suxin;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.*;
    
    //FFFbean实现了BeanNameAware、BeanFactoryAware、IntializaingBean、DiposableBean 这四种bean级别的生命周期接口方法
    //同时也写了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 执行中..."+name);
        }
    
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("FFFbean.setBeanFactory 执行中...");
        }
    
        public void afterPropertiesSet() throws Exception {
            System.out.println("FFFbean.afterPropertiesSet 执行中...");
        }
    
        public void destroy() throws Exception {
            System.out.println("FFFbean.destroy 执行中...");
        }
    
    
        public FFFbean() {
            System.out.println("FFFbean.构造方法 执行中...");
        }
    
        public void doSomething() {
            System.out.println("doSomething...");
        }
    
    
        public String getValue() {
            System.out.println("FFFbean.getValue 执行中... " + value);
            return value;
        }
    
        public void setValue(String value) {
            System.out.println("FFFbean.setValue 执行中... " + value);
            this.value = value;
        }
    
        public void initMethod() {
            System.out.println("FFFbean.initMethod...");
        }
    
        public void destroyMethod() {
            System.out.println("FFFbean.destroyMethod...");
        }
    }
    
    

    xml配置相关:

    <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>
    

    运行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();
    

    执行结果

    八月 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.构造方法 执行中...
    DDDbean...BeanFactoryPostProcessor.postProcessBeanFactory 执行中...
    EEEbean.构造方法 执行中...
    EEEbean.setName 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 执行中...
    FFFbean.构造方法 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessPropertyValues 执行中...
    FFFbean.setValue 执行中... jiujiu
    FFFbean.setBeanName 执行中...fFFbean
    FFFbean.setBeanFactory 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 执行中...
    FFFbean.afterPropertiesSet 执行中...
    FFFbean.initMethod...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInitialization 执行中...
    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 执行中...
    FFFbean.destroyMethod...
    
    Process finished with exit code 0
    
    

    ok,代码相关已经贴完,我们开始来解释一下。当然以上代码如果感兴趣可以直接复制下来,自己运行一遍,加深印象。

    贴一段AbstractApplicationContext的refresh方法的源码,我会忽略一些不是本章关注的代码

        @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 {
                    // 让继承容器的子类容器进行扩展的
                    postProcessBeanFactory(beanFactory);
    
                    // 创建BeanFactoryPostProcessor实例,并且调用相关方法,也就是在这个方法里DDDbean会被初始化,且会被调用相关方法
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // 初始化实现了BeanPostProcessor 和 InstantiationAwareBeanPostProcessor接口方法的bean,也就是说这里EEEbean被初始化 ps:还未调用相关方法
                    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.
                    // ...
    
                    // 完成初始化的工作,等会会深入进入看看
                    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核心中常见的默认缓存,因为我们
                    // 可能不再需要用于单例bean的元数据了…
                    resetCommonCaches();
                }
            }
        }
    

    首先是DDDbean的构造方法被执行了,然后继续执行这个bean的实现了BeanFactoryPostProcessor的postProcessBeanFactory方法。ok第一步已经出来了BeanFactoryPostProcessor这种级别的bean会被首先初始化然后紧接着就是调用该bean的postProcessBeanFactory方法。
    其发生的时机就是在AbstractApplicationContext的refresh方法里的调用invokeBeanFactoryPostProcessors方法
    贴一段invokeBeanFactoryPostProcessors的源码(已经删除非重点代码):

    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()));
            }
        }
    //继续看代码
    //PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    //这是个静态方法,由于代码很多我就忽略了非本章关注的代码
    public static void invokeBeanFactoryPostProcessors(
                ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
            // Invoke BeanDefinitionRegistryPostProcessors first, if any.
            Set<String> processedBeans = new HashSet<String>();
    
            // ......
    
            // 获取到所有工厂后处理器接口实现类的名字,DDDbean的名字就包含在里面
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
            // 为容器内的BeanFactoryPostProcessor规定创建顺序和执行方法的顺序
            // 优先级最高的是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.
            // ......
    
            // 关注这个部分,DDDbean即将在这里被初始化然后调用它的方法
            List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
            for (String postProcessorName : nonOrderedPostProcessorNames) {
                nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
            }
            invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
            // 清除缓存的合并bean定义,因为后处理器可能
            // 修改了原始元数据,例如替换值中的占位符…
            beanFactory.clearMetadataCache();
        }
    

    通过源码解读,我们可以了解到为什么DDDbean会优先被初始化且被调用实现的postProcessBeanFactory方法。
    接下来我们继续看到EEEbean被初始化(实例化+属性赋值),且相对于FFFbean来说是优先初始化。继续看源码,这一次我们深入到registerBeanPostProcessors(beanFactory)方法里去看。非本章关注代码已经忽略

    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
            PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }
    
    //继续深入进去看 省略无关代码
    public static void registerBeanPostProcessors(
                ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
            // 获取到了EEEbean的名字放在了postProcessorNames 数组里面
            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 {
                    //关注一下这个方法 EEEbean的名字被放到这个集合里面
                    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) {
                // 关注点在这里,初始化BeanPostProcessor相关类 也就是EEEbean在这里进行初始化(实例化+属性赋值)
                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一步进行初始化了。
    继续看源码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.
            // ......
    
            // 重点关注方法
            beanFactory.preInstantiateSingletons();
        }
    

    继续看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 {
                        //重点方法 关注一波
                        getBean(beanName);
                    }
                }
            }
    
            // Trigger post-initialization callback for all applicable beans...
            // ......
        }
    

    继续看getBean方法,其实就是看doGetBean方法(继续省略不是本章关注重点的代码):

    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.
                    // ......
    
                    // 关注单例的bean的创建 重点关注createBean方法
                    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()) {
                        // 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;
        }
    

    继续看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 {
                // 首先关注这个方法
                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的方法依然是我们关注的重点。
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            // ......
            return beanInstance;
        }
    

    ok,通过上面的代码我们已经提炼处我们需要关注的俩个方法:resolveBeforeInstantiation(beanName, mbdToUse)和doCreateBean(beanName, mbdToUse, args),ok我们一个个来看:
    首先是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) {
                        //就是这里会调用一次EEEbean的postProcessBeforeInstantiation方法,
                        // 具体的方法大家进去看一下非常简单。
                        bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                        if (bean != null) {
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                        }
                    }
                }
                mbd.beforeInstantiationResolved = (bean != null);
            }
            return bean;
        }
    

    上面的代码说明了EEEbean会被调用实现的postProcessBeforeInstantiation方法,同时因为该方法在EEEbean的实现里返回的是一个null,所以不会立即执行EEEbean的postProcessAfterInstantiation方法,会放在后面来执行。(对了此时我们得明白一下现在的情况,DDDbean和EEEbean已经被初始化了,但是FFFbean还没有完成初始化(按照目前的这个代码进度来说FFFbean的实例化还未完成))
    继续,我们来看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) {
                //关注一下这里,在这里会完成FFFbean的实例化,也就是FFFbean的构造方法会被调用
                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 {
                // 关注这个方法,会完成FFFbean的属性注入
                populateBean(beanName, mbd, instanceWrapper);
                if (exposedObject != null) {
                    // 关注这个方法,完成bean的相关实现方法的回调
                    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;
        }
    

    通过上面的源码我们可以看到主要有三个方法值得关注createBeanInstance、populateBean、initializeBean。createBeanInstance完成了FFFbean的实例化(也就是调用了FFFbean的构造方法)
    我们来重点关注一下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;
                        //关注这里,解释了为什么EEEbean执行了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) {
                            //关注一下这里,会执行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);
                }
            }
            //执行FFFbean的赋值操作,FFFbean的setValue方法
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    

    以上,populateBean方法解释完了,DDDbean和EEEbean都已经被初始化了而FFFbean已经完成了实例化和属性注值,现在就差FFFbean的实现相关接口的方法回调了。我们继续看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 {
                //重点关注一下这个方法,回调了FFFbean实现了
                //BeanNameAware和BeanFactoryAware接口的方法,具体的
                //大家点击进去看一下,代码很简单
                invokeAwareMethods(beanName, bean);
            }
    
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                //关注重点 此方法里回调了EEEbean的postProcessBeforeInitialization方法,大家可以自己点进去,非常简单明了
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
    
            try {
                //关注重点 在这个方法里主要执行了FFFbean实现了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()) {
                //关注重点  此方法里回调了EEEbean的postProcessAfterInitialization方法,大家可以自己点进去,非常简单明了
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
            return wrappedBean;
        }
    

    至此,FFFbean完成了初始化的所有工作(实例化+属性注入+接口方法回调),而且整个控制台打印的东西里doSomething之前的打印部分已经解释完毕。我们现在再把整个空调台打印的东西展示一下,防止大家忘记:

    八月 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.构造方法 执行中...
    DDDbean...BeanFactoryPostProcessor.postProcessBeanFactory 执行中...
    EEEbean.构造方法 执行中...
    EEEbean.setName 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 执行中...
    FFFbean.构造方法 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessPropertyValues 执行中...
    FFFbean.setValue 执行中... jiujiu
    FFFbean.setBeanName 执行中...fFFbean
    FFFbean.setBeanFactory 执行中...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization 执行中...
    FFFbean.afterPropertiesSet 执行中...
    FFFbean.initMethod...
    EEEbean...InstantiationAwareBeanPostProcessor.postProcessAfterInitialization 执行中...
    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 执行中...
    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对象执行了doSomething方法。紧接着就是容器的关闭。

    在容器关闭的方法里,会先调用FFFbean实现DisposableBean的destroy方法,然后再接着调用FFFbean本身的destoryMethod属性里的方法
    具体的感兴趣的可以自己看源码一步步的debug。

    跟着源码走一遍,估计大家这会都有点晕乎了,我们来做一些总结吧:
    首先Spring的bean的生命周期只有五步:实例化、属性赋值、初始化、使用、销毁。

    实例化、属性赋值、初始化分别对应三个方法,都是在doCreateBean方法里面,也就是createBeanInstance、populateBean、initializeBean。

    说完了bean的生命周期,我们来说一下各个接口的方法调用的时机。
    BeanFactoryPostProcessor类型的接口bean是最先被创建(实例化、属性注入、初始化)并且被调用的postProcessBeanFactory方法的。该时机是refresh方法里的invokeBeanFactoryPostProcessors方法里。refresh的registerBeanPostProcessors方法里主要是做了BeanPostProcessor类型(包括InstantiationAwareBeanPostProcessor)的创建(实例化、属性注入、初始化),而InstantiationAwareBeanPostProcessor类型的方法调用的时机是在doCreateBean里。

    InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法会在createBeanInstance(实例化)之前调用,而它的postProcessAfterInstantiation方法则会在createBeanInstance(实例化)之后调用。在populateBean(属性注入)方法里会调用它的postProcessPropertyValues。

    接下来就是各种bean级别的生命周期接口诸如beanNameAware、BeanFactoryAware都会在initializeBean(初始化方法里)里面首先调用,然后调用的是BeanPostProcessor接口的postProcessBeforeInitialization方法,后面接着就是InitializingBean接口的afterPropertiesSet方法,最后再次调用BeanPostProcessor接口的postProcessAfterInitialization方法。

    说完了创建阶段,再说一下销毁阶段,销毁阶段就是先调用DisposableBean接口的destroy方法,然后再调用bean自身的destroyMethod关联的方法。

    至此整个bean的生命周期和接口方法的扩展时机我们就说完了,可能有点多有点杂,大家多看看,最好能根据我的代码自己跑一遍debug一遍,相信就会了解的更加深刻。

    相关文章

      网友评论

          本文标题:SpringIOC中bean的生命周期

          本文链接:https://www.haomeiwen.com/subject/bwdidctx.html