美文网首页Spring 源码
Spring 的 BeanPostProcessor 原理剖析及

Spring 的 BeanPostProcessor 原理剖析及

作者: 守住阳光 | 来源:发表于2019-01-14 16:47 被阅读69次


    一、接口介绍

            spring提供了一个接口类 BeanPostProcessor,我们称其为后置处理器,作用是在 bean 的实例化的过程中对 bean 进行自定义的包装处理,其提供了两个方法。先看看 BeanPostProcessor 的定义。

    public interface BeanPostProcessor{ 

            public abstract Object postProcessBeforeInitialization(Object obj, String s) throws BeansException; 

              public abstract Object postProcessAfterInitialization(Object obj, String s) throws BeansException;  

    }

            根据类的名称,我们可以猜测两个接口方法执行的位置:

            1、在bean初始化之前执行;

       2、在bean的初始化之后执行。

    二、源码解析

            理解其原理以及执行的位置,需要到源码中寻找答案。跟踪创建 bean 的实例的 getBean 方法,层层跟进,在AbstractAutowireCapableBeanFactory 类中,找到了执行方法:

    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 {

                 invokeAwareMethods(beanName, bean); 

            }  

            Object wrappedBean = bean;

            if (mbd == null || !mbd.isSynthetic()) { 

                    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 

            } 

            try {          

                    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;

    }       

            如上加粗部分是主要的代码,invokeAwareMethods(beanName, bean)、 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);invokeInitMethods(beanName, wrappedBean, mbd)、invokeInitMethods(beanName, wrappedBean, mbd)、applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)。

            1、invokeAwareMethods(beanName, bean),对实现了 aware 接口的 bean 进行特殊的处理,实现aware 接口的 bean 在被初始化后,可以取得一些相对应的资源。比如, applicationAware , beanFactoryAware 等。

            2applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)后置处理器初始化前方法调用。

            3、invokeInitMethods(beanName, wrappedBean, mbd),用于用户初始化方法的调用,如实现了 InitializingBean 接口的 bean ,调用其 afterPropertiesSet 和 用户配置的 init-method 方法的调用。

            进入applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)和applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName),查看其源码:

    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { 

            Object result = existingBean; 

            for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { 

                    result = beanProcessor.postProcessBeforeInitialization(result, beanName); 

                    if (result == null) { 

                             return result;  

                    } 

             }   

             return result;  

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

            Object result = existingBean;

            for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

                result = beanProcessor.postProcessAfterInitialization(result, beanName);

                if(result ==null) {

                    return result;

                }

            }

            return result;

    }

    三、使用

    1、定义接口和实例 

    publi interface DemoService {

        public void sayHello();

    }

    public interface NameInit { 

         public void setName(String name);  

    }

    public class DemoServiceImpl implements DemoService,NameInit {

            String name; 

            @Override 

            public void sayHello() { 

                    System.out.println("hello "+name); 

            }     

            @Override      

            public void setName(String name) {  

                    this.name=name;    

            }

    }

    2、定义bean的配置

    <bean id="demoService" class="com.zjl.beanpostprocessor.DemoServiceImpl"> </bean>

    3、定义一个BeanPostProcessor 实例

            凡是继承了NameInit的接口,均实例化,注入name值。此处定义接口一方面是要使用接口中提供的setName方法,另一方面减轻系统压力,防止每个bean都进行注入。

    public class NameBeanPostProcessor implements BeanPostProcessor { 

            String name;

            public String getName() { 

                    return name;

             } 

            public void setName(String name) { 

                    this.name = name; 

            } 

            @Override         

            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 

                    if(bean instanceof NameInit){ 

                        ((NameInit)bean).setName(name);

                      }  

                    return bean; 

            }      

            @Override 

            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  

                    return bean;    

            }

     }  

    5、定义bean,注入name的值

    <bean id="nameBeanPostProcessor" class="com.zjl.beanpostprocessor.NameBeanPostProcessor">

            <property name="name" value="zhangsan"></property>  

    </bean>

    6、定义另一个BeanPostProcessor ,仅打印日志

    public class LogBeanPostProcessor implements BeanPostProcessor { 

            @Override                    

             public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 

                    System.out.println("正在处理"+beanName); return bean;  

            } 

            @Override      

            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 

                    System.out.println("已经处理完成"+beanName);   

                     return bean;

             }   

     } 

    7、定义bean

    <bean id="logBeanPostProcessor" class="com.zjl.beanpostprocessor.LogBeanPostProcessor"> </bean>

    8、测试类

    public class BeanPostProcessorTest { 

            public static void main(String[] args) { 

                    ApplicationContext context=new FileSystemXmlApplicationContext("beanpostprocessor.xml"); 

                    DemoService demoService=(DemoService) context.getBean("demoService"); 

                    demoService.sayHello();

             }       

    }

    9、测试结果

    正在处理demoService 

    已经处理完成demoService 

    hello zhangsan 

    10、总结

      两个方法均在bean实例化期间已经完成;

         name属性是根据NameInit接口自动注入;

      由于两个方法执行的时间特殊性,所以打印日志和记录时间意义不大,主要还是用于注入属性和完善配置。

    相关文章

      网友评论

        本文标题:Spring 的 BeanPostProcessor 原理剖析及

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