创建bean的流程五

https://cloud.tencent.com/developer/article/2284060

### -------doCreateBean------------initializeBean
 initializeBean方法主要是针对我们配置的init-method属性,当Spring中程序已经执行过bean的实例化,
 并且进行了属性的填充,而就在这时将会调用用户设定的初始化方法。具体源码如下所示:
-> AbstractAutowireCapableBeanFactory.initializeBean()


    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        invokeAwareMethods(beanName, bean);                                                             激活Aware方法

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) 
                                                                                                        调用配置的所有BeanPostProcessor#postProcessBeforeInitialization方法
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);                                               激活用户自定义的init方法
        } catch (Throwable ex) {throw new BeanCreationException(...);}
        
        if (mbd == null || !mbd.isSynthetic()) 
                                                                                                         调用配置的所有BeanPostProcessor#postProcessAfterInitialization方法
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        
        return wrappedBean;
    }


    invokeAwareMethods(...)激活Aware方法                           ???
        Spring中提供了一些Aware接口实现,比如:BeanFactoryAware、ApplicationContextAware、
        ResourceLoaderAware、ServletContextAware等,
        实现这些Aware接口的bean在被初始化之后,可以取得一些相对的资源。

    invokeInitMethods(...)激活自定义的init方法
        客户定制的初始化方法除了我们熟知的使用配置init-method外,
        还有使自定义的bean实现InitializingBean接口,并在afterPropertiesSet()方法中实现自己的初始化业务逻辑。
        其中,InitializingBean的afterPropertiesSet()方法先被执行,而init-method后执行。下面是相关源码实现:
        protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
            boolean isInitializingBean = (bean instanceof InitializingBean);
            if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
                if (logger.isTraceEnabled()) logger.trace(...);
                
                if (System.getSecurityManager() != null) {
                    try {
                        AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                            ((InitializingBean) bean).afterPropertiesSet(); // 属性初始化后的处理
                            return null;
                        }, getAccessControlContext());
                    }
                    catch (PrivilegedActionException pae) {throw pae.getException();}
                }
                // 属性初始化后的处理,调用InitializingBean#afterPropertiesSet()方法
                else ((InitializingBean) bean).afterPropertiesSet(); 
            }
            if (mbd != null && bean.getClass() != NullBean.class) {
                String initMethodName = mbd.getInitMethodName();
                if (StringUtils.hasLength(initMethodName) &&
                        !(isInitializingBean && 
                        "afterPropertiesSet".equals(initMethodName)) &&
                        !mbd.isExternallyManagedInitMethod(initMethodName)) {
                    // 调用自定义的init-method方法
                    invokeCustomInitMethod(beanName, bean, mbd);
                }
            }
        }

        protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {
            String initMethodName = mbd.getInitMethodName();                                                    获得init-method方法
            Assert.state(initMethodName != null, "No init method set");

            /** 步骤1:获得init-method对应的Method实例对象 */
            Method initMethod = (mbd.isNonPublicAccessAllowed() ?
                    BeanUtils.findMethod(bean.getClass(), initMethodName) :
                    ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
            if (initMethod == null) 
                if (mbd.isEnforceInitMethod()) throw new BeanDefinitionValidationException(...);
                else return;
            Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);

            /** 步骤2:通过反射,执行init-method的方法调用 */
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    ReflectionUtils.makeAccessible(methodToInvoke);
                    return null;
                });
                try {
                    AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
                            () -> methodToInvoke.invoke(bean), getAccessControlContext());
                } catch (PrivilegedActionException pae) {...}
            }
            else {
                try {
                    ReflectionUtils.makeAccessible(methodToInvoke);
                    methodToInvoke.invoke(bean);                                                                  通过反射,执行init-method的方法调用
                }
                catch (InvocationTargetException ex) {throw ex.getTargetException();}
            }
        }

    registerDisposableBeanIfNecessaryn(...)注册DisposableBean
        Spring同时也提供了销毁方法的扩展入口,对于销毁方法的扩展,除了我们熟知的配置属性destroy-method方法外,
        用户还可以注册后处理器DestructionAwareBeanPostProcessor来统一处理bean的销毁方法,具体源码如下所示:

        protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
            AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
            if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
                /** 
                 * 单例模式下注册需要销毁的bean,此方法中会处理实现DisposableBean的bean,
                 * 并且对所有的bean使用DestructionAwareBeanPostProcessor处理
                 */
                if (mbd.isSingleton())  
                    registerDisposableBean(beanName, new DisposableBeanAdapter(bean, 
                                                                     beanName, 
                                                                     mbd, 
                                                                     getBeanPostProcessorCache().destructionAware, 
                                                                     acc));
                else { // 自定义scope的处理
                    Scope scope = this.scopes.get(mbd.getScope());
                    if (scope == null) throw new IllegalStateException(...);
                    scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, 
                                                                     beanName, 
                                                                     mbd, 
                                                                     getBeanPostProcessorCache().destructionAware, 
                                                                     acc));
                }
            }
        }


            /**
            * AbstractAutoProxyCreator类中的bean后置处理器中的后方法
            */
            @Override
            public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
                if (bean != null) {
                    Object cacheKey = getCacheKey(bean.getClass(), beanName);
                    // 有AOP的情况下会调用getEarlyBeanReference方法,在getEarlyBeanReference方法中会将原本的bean放入到earlyProxyReferences中,
                    所以remove出来的bean和参数中的bean是同一个,条件不成立,所以不会再生成一个新的代理对象
                    // 如果没有aop,就不会调用getEarlyBeanReference方法,earlyProxyReferences是空的,remove出来是null,条件成立,就会生成一个代理对象
                    if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                        return wrapIfNecessary(bean, beanName, cacheKey);
                    }
                }
                return bean;
            }    


 

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值