BeanPostProcessor由浅入深

  • Post author:
  • Post category:其他




BeanPostProcessor由浅入深:



1、BeanPostProcessor原理:

该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。流程图如下(如何使用这里就不附上代码,相信大家已经了解)

首先-初始化bean—>检查容器中是否存在BeanPostProcessor,

如果存在就调用postProcessBeforeInitialization方法

.

—>如果返回null(或者所有的BeanPostProcessor执行完毕)

.

—->执行bean的初始化方法

.

—->再次判断容器中是否存在BeanPostProcessor

.

—>如果存在就调用postProcessAfterInitialization方法

.

—>如果返回null(或者所有的BeanPostProcessor执行完毕)

.

—>运行结束

如果一开始容器中就没有 BeanPostProcessor,那么就会直接支持bean的初始化方法,结束;(结合流程与源码一起会更加清晰,下附源码)

2、容器启动到Bean创建–底层源码流程:

test方法—-…—->refresh()

—->finishBeanFactoryInitialization()

.

—->preInstantiateSingletons()

.

—->preInstantiateSingletons()

.

—->getBean()

.

—->doGetBean()

.

—-> getSingleton(beanName, new ObjectFactory()

这是一个简单的流程,可以大致看一下在容器启动的时候具体调用了哪些方法;

我们先进入doGetBean方法里面:发现其实是调用了getSingleton方法获取实例,

如果没有获取到又通过getObject()里面的 createBean(beanName, mbd, args)创建实例,总之这个实例一定要创建出来


因为长度问题这里只取这篇文章对最关键的一部分展示(谅解一下)

doGetBean()
.....................................................
if (mbd.isSingleton()) {
    //  获取单实例bean  获取不到的话就通过getObject()里面的 createBean(beanName, mbd, args); 创建实例
      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;
         }
         }
     });
   createBean(beanName, mbd, args)里面实际又调用 Object beanInstance = doCreateBean(beanName, mbdToUse, args) 创建实例 并用Object接收

3、让我们看看doCreateBean是如何创建bean实例的:

protected Object doCreateBean(final String beanName, final RootBeanDefinition  mbd, final Object[] args)
                    throws BeanCreationException {
             // Instantiate the bean.
             BeanWrapper instanceWrapper = null;
       ...........................................................
             Object exposedObject = bean;
             try {
                          //在里面进行各种判断为属性赋值,先为属性赋值,下面再调用initializeBean()
                    populateBean(beanName, mbd, instanceWrapper);
                    if (exposedObject != null) {
                                  //后置处理器的调用,以及bean的初始化都在此被执行(ง •_•)ง ,后面进入initializeBean方法
                           exposedObject = initializeBean(beanName,  exposedObject, mbd);
                    }
             }
             catch (Throwable ex) {
                    if (ex instanceof BeanCreationException &&  beanName.equals(((BeanCreationException) ex).getBeanName())) {
                           throw (BeanCreationException) ex;
                    }
                    else {
                           throw new BeanCreationException(
                                        mbd.getResourceDescription(), beanName,  "Initialization of bean failed", ex);
                    }
             }
       ...........................................................
             return exposedObject;
       }

4、

initializeBean

方法(也就是

BeanPostProcessor

最关键的执行步骤):

  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()) {
                                              **// 1. 应用后处理器的BeforeInitialization方法**
                    wrappedBean =  applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
             }
             try {
                      **//调用bean的初始化方法**
                    invokeInitMethods(beanName, wrappedBean, mbd);   **ini-method**
             }
             catch (Throwable ex) {
                    throw new BeanCreationException(
                                 (mbd != null ? mbd.getResourceDescription() :  null),
                                 beanName, "Invocation of init method failed",  ex);
             }
             if (mbd == null || !mbd.isSynthetic()) {
                                      **// 3. 调用后处理器的AfterInitialization方法**
                    wrappedBean =  applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
             }
             return wrappedBean;
             }
       }
    

可以看到,初始化方法是在BeanPostProcessor执行之后才执行的,下面让我们了解一下applyBeanPostProcessorsBeforeInitialization具体是如何获取,并执行的

5、

applyBeanPostProcessorsBeforeInitialization

进入方法,首先通过foreach遍历容器中得到的所有BeanPostProcessor;挨个执行beforeInitialization,

一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization(同理applyBeanPostProcessorsAfterInitialization也是如此)

 @Override
   public Object applyBeanPostProcessorsBeforeInitialization(Object  existingBean, String beanName)
                throws BeansException {
         Object result = existingBean;
         for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
                   //初始化之前按调用了BeforeInitialization方法
                result =  beanProcessor.postProcessBeforeInitialization(result, beanName);
                if (result == null) {
                       return result;
                }
         }
         return result;
   }

3、总的来说,就是再doCreateBean创建bean的时候调用了populateBean(beanName, mbd, instanceWrapper)方法给bean进行属性赋值。

⭐(细节问题:一定时先给bean属性赋值,再调用的BeanPostProcessor,初始化方法)在属性赋值以后调用了初始化bean的方法initializeBean

在initializaBean里面就调用了后置处理器,可以发现,BeanPostProcessor是在初始化方法前后调用的(ini-method)

 {
 1- applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 2- invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
 3- applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 }

6、尾:

谈一下

BeanPostProcessor

及其子类:(这里只涉及一下

ApplicationContextAwareProcessor

1、

InitDestroyAnnotationBeanPostProcessor


处理初始化方法(我们初始化方法是如何执行的,如何被容器发现的,都是因为这个组件在工作,可在int-method打断点看看具体调试)

2、

AutowiredAnnotationBeanPostProcessor


处理自动装配,为什么Spring可以自动装配呢,当然是因为有这个类了,这里就不多说。

3、

BeanValidationPostProcessor

主要是用来数据校验,一般在MVC里面用的比较多

4、

ApplicationContextAwareProcessor

作用是帮我们组件里面注入IOC容器 如何注入呢?看代码

只需要实现ApplicationContextAware接口,并且重写setApplicationContext方法,再将ApplicationContext对象传入即可
@Component
public class Dog implements ApplicationContextAware { 
       
       //@Autowired
       private ApplicationContext applicationContext;
       
       @Override
       public void setApplicationContext(ApplicationContext applicationContext)  throws BeansException {
             // TODO Auto-generated method stub
             this.applicationContext = applicationContext;
       }

走一下源码:
从initializeBean初始化bean的时候里面调用了applyBeanPostProcessorsBeforeInitialization--->postProcessBeforeInitialization--->invokeAwareInterfaces
       @Override
       public Object postProcessBeforeInitialization(final Object bean, String  beanName) throws BeansException {
             AccessControlContext acc = null;
             if (System.getSecurityManager() != null &&
                           (bean instanceof EnvironmentAware || bean instanceof  EmbeddedValueResolverAware ||
                                        bean instanceof ResourceLoaderAware ||  bean instanceof ApplicationEventPublisherAware ||
                                        bean instanceof MessageSourceAware ||  bean instanceof ApplicationContextAware)) {  在这里进行了判断,判断是否实现了ApplicationContextAware以及这些其他的的接口
                    acc =  this.applicationContext.getBeanFactory().getAccessControlContext();
             }
             if (acc != null) {
                    AccessController.doPrivileged(new PrivilegedAction<Object>()  {
                           @Override
                           public Object run() {
                                 invokeAwareInterfaces(bean); 如果是的话就调用invokeAwareInterfaces给里面注入值,怎么注入的,看下面的方法;(虽然是if语句,但是都会进行判断,注意细节)
                                 return null;
                           }
                    }, acc);
             }
             else {
                    invokeAwareInterfaces(bean);
             }
             return bean;
       }
     注入:
       private void invokeAwareInterfaces(Object bean) {  判断是哪个Aware,那把哪个Aware注入进去
             if (bean instanceof Aware) {
                    if (bean instanceof EnvironmentAware) {
                           ((EnvironmentAware)  bean).setEnvironment(this.applicationContext.getEnvironment());
                    }
                    if (bean instanceof EmbeddedValueResolverAware) {
                           ((EmbeddedValueResolverAware)  bean).setEmbeddedValueResolver(this.embeddedValueResolver);
                    }
                    if (bean instanceof ResourceLoaderAware) {
                           ((ResourceLoaderAware)  bean).setResourceLoader(this.applicationContext);
                    }
                    if (bean instanceof ApplicationEventPublisherAware) {
                           ((ApplicationEventPublisherAware)  bean).setApplicationEventPublisher(this.applicationContext);
                    }
                    if (bean instanceof MessageSourceAware) {
                           ((MessageSourceAware)  bean).setMessageSource(this.applicationContext);
                    }
                    if (bean instanceof ApplicationContextAware) {  
这里我们是ApplicationContextAware,所以直接把bean强转ApplicationContextAware再调用setApplicationContext,直接把IOC容器注入进去,然后就实现了向组件里面注入ioc容器了
                           ((ApplicationContextAware)  bean).setApplicationContext(this.applicationContext);
                    }
             }
       }



如果哪里不足,还请指出,大家一起共同进步(

^ _^

),加油。

##BeanPostProcessor原理由浅入深



版权声明:本文为qq_46127735原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。