zoukankan      html  css  js  c++  java
  • Ioc容器BeanPostProcessor-Spring 源码系列(3)

    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代码耦合在一起了。

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

    永远爱汀汀

  • 相关阅读:
    MYSQL 写入emoji表情字符处理
    openfire4.0.2源码 使用 IntelliJ IDEA 搭建开发环境
    strophe.js 插件 XMPP openfire
    OPENFIRE 使用Hazelcast插件进行集群
    LINUX提高openfire并发数(网上收集)
    LINUX 安装JDK (rpm格式和tar.gz格式)
    OPENFIRE 接收数据流程图
    OPENFIRE 启动流程
    linux查看cuda版本
    NvvmSupportError: libNVVM cannot be found. Do conda install cudatoolkit: library nvvm not found
  • 原文地址:https://www.cnblogs.com/killbug/p/6349612.html
Copyright © 2011-2022 走看看