美文网首页
initMethod 和 afterPropertiesSet

initMethod 和 afterPropertiesSet

作者: Y了个J | 来源:发表于2021-08-04 12:49 被阅读0次

    在AbstractAutowireCapableBeanFactory类中

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
            // Instantiate the bean.
            BeanWrapper instanceWrapper = null;
            if (mbd.isSingleton()) {
                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
            }
            if (instanceWrapper == null) {
                instanceWrapper = createBeanInstance(beanName, mbd, args);
            }
            //...省略很多代码 下面开始初始化 关键就是两个步骤
            // Initialize the bean instance.
            Object exposedObject = bean;
            try {
                populateBean(beanName, mbd, instanceWrapper);   //这里执行了注入属性和依赖的操作
                if (exposedObject != null) {
                    exposedObject = initializeBean(beanName, exposedObject, mbd);//这里执行了initMethod 和 afterPropertiesSet
                }
            }
             //...省略很多代码 
            return exposedObject;
        }
    

    重点看initializeBean(beanName, exposedObject, mbd)

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        invokeAwareMethods(beanName, bean);
    
                        return null;
                    }
                }, getAccessControlContext());
            }
            else {
                //这里判断是BeanFactoryAware, ServletContextAware之类的aware类型,如果是的话就执行对于的Aware方法
                //把beanFactory啊 servletContext啊之类的依赖set进去
                invokeAwareMethods(beanName, bean);
            }
            
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {   
                //如果实现了BeanPostProcessor接口 这里会执行postProcessBeforeInitialization方法
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
            try {
                //这里就开始执行initMethod 和 afterPropertiesSet方法
                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()) {
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
            return wrappedBean;
        }
    

    进入invokeInitMethods(beanName, wrappedBean, mbd);

    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
                throws Throwable {
            boolean isInitializingBean = (bean instanceof InitializingBean);//先判断是否实现了InitializingBean接口
            if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
                 //.....省略很多代码            
                else {
                    //执行afterPropertiesSet()方法
                    ((InitializingBean) bean).afterPropertiesSet(); 
                }
            }
            if (mbd != null) {
                String initMethodName = mbd.getInitMethodName();
                if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                        !mbd.isExternallyManagedInitMethod(initMethodName)) {
                    //如果配置了initMethod 就执行initMethod方法 这里只是取到了方法名,显然是要通过反射调用了
                    invokeCustomInitMethod(beanName, bean, mbd);
                }
            }
        }
    

    经过这些源码的分析 可以得出结论
    首先这些过程都在很重要的抽象类AbstractAutowireCapableBeanFactory抽象类中 这个类就是常用的DefaultListableBeanFactory的父类
    1.spring先根据beanDefinition创建出了bean 的实例

    2.执行了populateBean方法 把属性和依赖都注入了

    3.执行了 initializeBean(beanName, exposedObject, mbd);方法 这里面才进行了Aware相关方法,afterPropertiesSet 和 initMethod 方法的调用
    可见这3种方法调用又都是在bean实例已经创建好,且属性值和依赖的其他bean实例都已经注入以后 才得到调用的

    4.后面的代码可以看出 Aware相关方法最先执行,afterPropertiesSet 第二执行 ,initMethod 方法最后执行

    另外多说一句 afterPropertiesSet方法是很有用的,比如 AOP事务管理用到的类,TransactionProxyFactoryBean 就是利用afterPropertiesSet方法事先把事务管理器
    TransactionManager的代理类对象给生成好了,后面调用FactoryBean对象的getObject方法的时候,就直接把这个代理对象返回出去了。

    相关文章

      网友评论

          本文标题:initMethod 和 afterPropertiesSet

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