zoukankan      html  css  js  c++  java
  • Spring源码系列4

    下图展示的是Bean从创建,装载到容器,到最终被销毁的整个生命周期过程。

    1.实例化Bean(createBeanInstance)

    创建Bean实例。根据指定bean使用相应的策略来创建Bean,如:工厂方法(instantiateUsingFactoryMethod)、构造方法注入(autowireConstructor)、简单初始化(instantiateBean)。

    Bean的实例化过程中并未进行属性的注入,仅仅是简单的实例化。实例化的Bean被包装成了BeanWrapper对象,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制来设置属性。

    AbstractAutowireCapableBeanFactory类中的doCreateBean方法

        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
            // Make sure bean class is actually resolved at this point.
            Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
            //确保Bean的class必须是public
            if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
            }
    
            //1.使用工厂方法创建Bean。(有factoryMethodName属性,说明配置文件中配置了factory-method)
            if (mbd.getFactoryMethodName() != null)  {
                return instantiateUsingFactoryMethod(beanName, mbd, args);
            }
    
            // Shortcut when re-creating the same bean...
            boolean resolved = false;
            boolean autowireNecessary = false;
            if (args == null) {
                synchronized (mbd.constructorArgumentLock) {
                    //一个类有多个构造方法,每个构造函数都有不同的参数,所以调用前需要先根据参数锁定构造方法或对应的工厂方法
                    if (mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }
            //如果已经解析过,则直接使用解析好的构造方法,不需要再次锁定
            if (resolved) {
                if (autowireNecessary) {
                    //2.使用构造器自动注入
                    return autowireConstructor(beanName, mbd, null, null);
                }
                else {
                    //3.使用默认构造方法
                    return instantiateBean(beanName, mbd);
                }
            }
    
            // Need to determine the constructor...
            //需要根据参数解析构造方法
            Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
            if (ctors != null ||
                    mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
                //构造方法自动注入
                return autowireConstructor(beanName, mbd, ctors, args);
            }
    
            // No special handling: simply use no-arg constructor.
            //使用默认构造方法
            return instantiateBean(beanName, mbd);
        }

    2.设置Bean属性(populateBean)

    实例化后的对象被包装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。 紧接着,Spring根据BeanDefinition中的信息进行依赖注入,并且通过BeanWrapper提供的设置属性的接口完成依赖注入。

    如果Bean有依赖,则在为属性赋值时会先通过getBean去获取依赖的Bean。这在Spring源码系列3 - IOC容器的启动过程中分析Bean的循环引用问题时讲述过,这里不再赘述。

        /**
         * Populate the bean instance in the given BeanWrapper with the property values
         * from the bean definition.
         * @param beanName the name of the bean
         * @param mbd the bean definition for the bean
         * @param bw the BeanWrapper with bean instance
         */
        protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
            PropertyValues pvs = mbd.getPropertyValues();
    
            if (bw == null) {
                if (!pvs.isEmpty()) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
                }
                else {
                    // Skip property population phase for null instance.
                    return;
                }
            }
    
            // 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.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                            return;
                        }
                    }
                }
            }
    
            int resolvedAutowireMode = mbd.getResolvedAutowireMode();
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
                // Add property values based on autowire by name if applicable.
                if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                    autowireByName(beanName, mbd, bw, newPvs);
                }
                // Add property values based on autowire by type if applicable.
                if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                    autowireByType(beanName, mbd, bw, newPvs);
                }
                pvs = newPvs;
            }
    
            boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
            boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    
            if (hasInstAwareBpps || needsDepCheck) {
                PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                if (hasInstAwareBpps) {
                    for (BeanPostProcessor bp : getBeanPostProcessors()) {
                        if (bp instanceof InstantiationAwareBeanPostProcessor) {
                            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                            if (pvs == null) {
                                return;
                            }
                        }
                    }
                }
                if (needsDepCheck) {
                    checkDependencies(beanName, mbd, filteredPds, pvs);
                }
            }
    
            applyPropertyValues(beanName, mbd, bw, pvs);
        }

    3.初始化Bean

    实际上在Spring源码系列3 - IOC容器的启动过程中,我们就已经总结过Bean的创建过程。Bean的创建过程主要经过下面几个过程。

    其中的第②步,是在Bean初始化之前做一些后置操作,比如@PostConstruct指定的初始化方法就是在此执行,处理该过程的组件是InitDestroyAnnotationBeanPostProcessor。而第④步,与第②步对应。是在Bean初始化之后做一些后置操作。

    下面,我们就来从源码入手分析一下Bean的初始化,也就是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 { 
                //① 调用Aware相关方法
                invokeAwareMethods(beanName, bean);
            }
    
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                //② Bean初始化前调用后置处理方法。【@PostConstruct指定方法在此调用】
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
    
            try { 
                //③ 调用初始化方法(afterPropertiesSet方法,init方法)
                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()) {
                //④ Bean初始化之后调用后置处理方法
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
            return wrappedBean;
        }

    initializeBean-->invokeInitMethods

        protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
                throws Throwable {
            //如果实现了InitializingBean接口
            boolean isInitializingBean = (bean instanceof InitializingBean);
            if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
                }
                if (System.getSecurityManager() != null) {
                    try {
                        AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                            @Override
                            public Object run() throws Exception {
                                ((InitializingBean) bean).afterPropertiesSet();
                                return null;
                            }
                        }, getAccessControlContext());
                    }
                    catch (PrivilegedActionException pae) {
                        throw pae.getException();
                    }
                }
                else {
                    //1.调用afterPropertiesSet方法【若实现了InitializingBean接口,afterPropertiesSet方法在此调用】
                    ((InitializingBean) bean).afterPropertiesSet();
                }
            }
    
            if (mbd != null) {
                String initMethodName = mbd.getInitMethodName();
                if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                        !mbd.isExternallyManagedInitMethod(initMethodName)) {
                    //2.调用自定义的init方法【@Bean中指定的初始化方法在此调用】
                    invokeCustomInitMethod(beanName, bean, mbd);
                }
            }
        }

    如果该Bean实现了InitializingBean接口,则会调用afterPropertiesSet方法。最后执行@Bean中指定的初始化方法。

    4.使用Bean

    也就是getBean的过程,从容器中获取Bean。

    5.销毁Bean

    注册DisposableBean和destroy-method

    Spring中不但提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口。对于销毁方法的扩展,除了我们熟知的配置属性destroy-method方法外,用户还可以注册后置处理器(DestructionAwareBeanPostProcessor)来统一处理bean的销毁方法。前面分析了初始化Bean的过程,最后有一个registerDisposableBeanIfNecessary步骤,其正是用于在Bean初始化完成后注册销毁方法的。

        protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
            AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
            if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
                if (mbd.isSingleton()) {
                    // Register a DisposableBean implementation that performs all destruction
                    // work for the given bean: DestructionAwareBeanPostProcessors,
                    // DisposableBean interface, custom destroy method.
                    //单例模式下注册需要销毁的Bean,此方法中会处理实现DisposableBean接口的Bean。
                    //并且对所有的bean使用DestructionAwareBeanPostProcessors处理
                    registerDisposableBean(beanName,
                            new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
                }
                else {
                    // A bean with a custom scope...
                    //非单例Bean的处理(scope值为非singleton)
                    Scope scope = this.scopes.get(mbd.getScope());
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
                    }
                    scope.registerDestructionCallback(beanName,
                            new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
                }
            }
        }

    销毁Bean

    destroy-->close-->doClose-->destroyBeans()
        -->DefaultListableBeanFactory#destroySingletons-->
             -->DefaultSingletonBeanRegistry#destroySingleton-->destroyBean
                  -->DisposableBeanAdapter#destroy()

        @Override
        public void destroy() {
            if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
                for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
                    //1.JSR250:调用@PreDestroy指定的销毁方法
                    processor.postProcessBeforeDestruction(this.bean, this.beanName);
                }
            }
    
            if (this.invokeDisposableBean) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
                }
                try {
                    if (System.getSecurityManager() != null) {
                        AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                            @Override
                            public Object run() throws Exception {
                                ((DisposableBean) bean).destroy();
                                return null;
                            }
                        }, acc);
                    }
                    else {
                        //2.如果Bean实现了DisposableBean接口,则调用Bean自身的destory方法
                        ((DisposableBean) bean).destroy();
                    }
                }
                catch (Throwable ex) {
                    String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
                    if (logger.isDebugEnabled()) {
                        logger.warn(msg, ex);
                    }
                    else {
                        logger.warn(msg + ": " + ex);
                    }
                }
            }
    
            if (this.destroyMethod != null) {
                //3.调用@Bean注解中destroyMethod属性执行的销毁方法
                invokeCustomDestroyMethod(this.destroyMethod);
            }
            else if (this.destroyMethodName != null) {
                Method methodToCall = determineDestroyMethod();
                if (methodToCall != null) {
                    invokeCustomDestroyMethod(methodToCall);
                }
            }
        }

    由上面代码可得知,Bean销毁的几种方式的先后调用顺序如下图。

    最后,在Spring源码系列5 - Bean的初始化/销毁的几种方式总结中对Bean的初始化和销毁的几种方式再次进行了总结。

    面试题:

    1.Bean的生命周期?

    2.Bean的作用域?

  • 相关阅读:
    存储数据的大小端模式
    双链表插入 删除详解
    php_match/preg_match_all 默认有字符串长度限制
    百度编辑器:获取编辑器的内容
    phalcon: update修改数据却变成了insert插入数据
    MySQL按照汉字的拼音排序,mysql汉字排序
    [转载]Eclipse提示No java virtual machine
    lhgdialog: iframe页面里面的,确定,关闭、取消按钮的操作
    js树目录结构
    mysql:恢复mysql表结构
  • 原文地址:https://www.cnblogs.com/rouqinglangzi/p/10768899.html
Copyright © 2011-2022 走看看