Ioc容器-BeanPostProcessor-Spring 源码

Posted 干掉自己

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ioc容器-BeanPostProcessor-Spring 源码相关的知识,希望对你有一定的参考价值。

Ioc容器BeanPostProcessor-Spring 源码系列(3)

 

目录:

 

Ioc容器beanDefinition-Spring 源码(1)

Ioc容器依赖注入-Spring 源码(2)

Ioc容器BeanPostProcessor-Spring 源码(3)

事件机制-Spring 源码(4)

AOP执行增强-Spring 源码系列(5)

 

 

如果这个接口的某个实现类被注册到某个容器,那么该容器的每个受管Bean在调用初始化方法之前,都会获得该接口实现类的一个回调。容器调用接口定义的方法时会将该受管Bean的实例和名字通过参数传入方法,进过处理后通过方法的返回值返回给容器。

根据这个原理,我们就可以很轻松的自定义受管Bean。
 
以下为使用例子的代码:
public class BeanPostProcessorTest implements BeanPostProcessor, Ordered {
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        return o;
    }

    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("beanName:"+s);
        return o;
    }

    /**
     * 多个BeanPostProcessor 用order来排序
     * @return
     */
    public int getOrder() {
        return 0;
    }
}

public static void main(String[] args) throws Exception {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("Spring-Customer.xml");
    }
<bean class="aspect.test.spring.BeanPostProcessorTest" />

《定时任务管理中心》文中就是用这种方式讲需要管理的bean过滤出来的。

这篇就解析一下spring 源码是哪里触发的,如何完成的。

postProcessAfterInitialization的调用链如图:

 

在上一篇中提到,doCreateBean就是创建bean的入口,在做线方法:populateBean(beanName, mbd, instanceWrapper);之后执行的initializeBean(beanName, exposedObject, mbd);触发的,直接看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 {
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      // 执行ProcessorsBefore的方法
      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()) {
     //执行ProcessorsAfter的方法
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
   return wrappedBean;
}

这里就先只看applyBeanPostProcessorsAfterInitialization:

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;
}

好了,到这里就调用到了所有BeanPostProcessors的实现。前面的代码其实有点像观察者模式的调用。

那么根据order顺序来执行BeanPostProcessors实现就是按顺序在放这个List<BeanPostProcessor>里,实现的代码如下:

public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   // Register BeanPostProcessorChecker that logs an info message when
   // a bean is created during BeanPostProcessor instantiation, i.e. when
   // a bean is not eligible for getting processed by all BeanPostProcessors.
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   // Separate between BeanPostProcessors that implement PriorityOrdered,
   // Ordered, and the rest.
   // 实现Ordered接口的
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
   // 未实现Ordered接口的
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
   List<String> orderedPostProcessorNames = new ArrayList<String>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
   for (String ppName : postProcessorNames) {
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
         priorityOrderedPostProcessors.add(pp);
         if (pp instanceof MergedBeanDefinitionPostProcessor) {
            //反而没有实现ordered的先放
            internalPostProcessors.add(pp);
         }
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   // First, register the BeanPostProcessors that implement PriorityOrdered.
   sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   // Next, register the BeanPostProcessors that implement Ordered.
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
   for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   sortPostProcessors(beanFactory, orderedPostProcessors);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);

   // Now, register all regular BeanPostProcessors.
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
   for (String ppName : nonOrderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      nonOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         internalPostProcessors.add(pp);
      }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

   // Finally, re-register all internal BeanPostProcessors.
   sortPostProcessors(beanFactory, internalPostProcessors);
   registerBeanPostProcessors(beanFactory, internalPostProcessors);
  
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

 

InitializingBean

 InitializingBean是使用Spring的时候比较常用的。继承InitializingBean,实现afterPropertiesSet方法,就可以实现在这个bean创建好的时候触发做一些事情,比如读取必要的配置,缓存文件,初始化信息等操作。

InitializingBean接口:

public interface InitializingBean {

    /**
     * Invoked by a BeanFactory after it has set all bean properties supplied
     * (and satisfied BeanFactoryAware and ApplicationContextAware).
     * <p>This method allows the bean instance to perform initialization only
     * possible when all bean properties have been set and to throw an
     * exception in the event of misconfiguration.
     * @throws Exception in the event of misconfiguration (such
     * as failure to set an essential property) or if initialization fails.
     */
    void afterPropertiesSet() throws Exception;

}

使用代码:

public class InitializingBeanTest implements InitializingBean {
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet do something");
    }
}

这里看一下spring哪里出发执行的这个接口,其实我们在上篇中已经看见入口了,就是initializeBean方法中执行的applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization方法的中间就是初始化操作方法:invokeInitMethods(beanName, wrappedBean, mbd);

代码很明了:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {

    //bean是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 {
              // 执行afterPropertiesSet方法
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();
       // 这里判断是否设置了int-method属性,如果设置则执行invokeCustomInitMethod
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

上面代码最下面我们可以看到可以利用int-method属性一样可以实现初始化bean时进行一些操作,好处是不需要继承spring的接口,就不用和spring代码耦合在一起了。

 

 

 

 

----------------------

永远爱汀汀

 

以上是关于Ioc容器-BeanPostProcessor-Spring 源码的主要内容,如果未能解决你的问题,请参考以下文章

Spring IOC容器源码流程

spring学习总结007 --- IOC容器级生命周期接口

spring IOC 容器中 Bean 的生命周期

spring源码分析IOC容器初始化——查漏补缺

Spring源码--01--Spring IOC简述

Bean后置处理器 BeanPostProcessor