美文网首页FAQ
Spring BeanPostProsser最佳实践

Spring BeanPostProsser最佳实践

作者: liaijuyyer | 来源:发表于2021-11-10 23:09 被阅读0次

    BeanPostProcessor接口的作用是在Spring bean 实例化完成后(执行完initializeBean)之后,初始化之前(执行bean的初始化方法)对Bean添加一些自定义的处理逻辑。也就是说执行beanProcessor方法是在bean实例化之后 此时bean的属性值都已经被赋值好了。另外需要注意的是 beanProcessor的实现类一定要被Spring托管才能生效。

    一、BeanPostProcessor示例

    • 实体类

        @Component
        @ConfigurationProperties(prefix = "spring.datasource")
        public class DataSourceProperty {
        
        
            private String userName;
        
            private String password;
        
            /**
             * 通过@PostConstruct来标记这个init方法为bean的初始化方法
             **/
            @PostConstruct
            private void init() {
                //这条语句会在 beanprocessor的postProcessBeforeInitialization方法执行之后执行 2
                System.out.println("执行初始化方法");
            }
        
            public String getUserName() {
                return userName;
            }
        
            public void setUserName(String userName) {
                this.userName = userName;
            }
        
            public String getPassword() {
                return password;
            }
        
            public void setPassword(String password) {
                this.password = password;
            }
        }
      
    • 配置

      spring.datasource.username=test
      spring.datasource.password=12345678
      
    • 自定义的BeanPostProcessor实现类

        //这个类一定要被spring容器托管(也就是要能够被spring识别为一个bean) postProcessBeforeInitialization 和 
        //postProcessAfterInitialization才会生效
        @Component
        public class MyBeanPostProcessor implements BeanPostProcessor {
        
            /**
             * bean实例化前处理
             * @param bean
             * @param beanName
             * @return
             * @throws BeansException
             */
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof DataSourceProperty) {
                            //这条语句是最先打印的 1  DataSourceProperty 此时它的两个属性是已经被赋值了的
                    System.out.println("dataSourceProperty 初始化前执行 dataSourceProperty" );
                }
                return bean;
            }
        
            /**
             * bean实例化后处理
             * @param bean
             * @param beanName
             * @return
             * @throws BeansException
             */
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof DataSourceProperty) {
                    //这条语句是最后打印的
                    System.out.println("dataSourceProperty 初始后执行" );
                }
                return bean;
            }
        }
      
    • 结果

    二、为什么BeanPostProcessor必须被Spring托管才能生效
    关于这一点可以查看源码

    • 第一步
      当Spring容器启动时 会先执行AbstractApplicationContext类的refresh方法 通过该方法去初始化我们的Spring容器 源码如下
        public abstract class AbstractApplicationContext extends DefaultResourceLoader
                implements ConfigurableApplicationContext {
            @Override
            public void refresh() throws BeansException, IllegalStateException {
                synchronized (this.startupShutdownMonitor) {
                    //省略前面若干方法
                    prepareBeanFactory(beanFactory);
        
                    try {
                //此处省略若干方法
                        // 向Spring容器注册beanProstProcessor
                        registerBeanPostProcessors(beanFactory);
                        beanPostProcess.end();
                        //此处省略若干方法 完成Spring容器刷新工作
                        finishRefresh();
                    }catch (BeansException ex) {
                        //此处省略
                    }finally {
                        //此处生路
                    }
                }
            }
        }
      
    • 第二步
      从第一步 我们知道了当Spring容器在执行refresh方法的时候 会向容器中注册beanProcessor 下面接着看registerBeanPostProcessors(beanFactory)方法的逻辑 该方法的真正实现是在PostProcessorRegistrationDelegate类中
        final class PostProcessorRegistrationDelegate {
          public static void registerBeanPostProcessors(
                    ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
                //核心方法 从beanFactory中获取容器中所有实现了BeanPostProcessor接口的bean的名称
                String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
            //此后省略若干方法
            }
        }
      
    • 第三步
      beanFactory.getBeanNamesForType() 这个方法真正的实现是在DefaultListableBeanFactory中
        public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
                implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
            
          @Override
            public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
                if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
                    //真正获取beanPostProcessor的名称的方法
              return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
                }
                //此处省略若干方法
                return resolvedBeanNames;
            }
        }
      
    • 第四步
        public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
                implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
          
          private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
                List<String> result = new ArrayList<>();
        
                // 它会遍历Spring容器的beanDefinitionNames 
                for (String beanName : this.beanDefinitionNames) {
                      //此处省略若干方法
                //如果类型是指定的类型 则将这个bean的名称加入到list中
                //对于BeanPostProcessor来说 此时type就是BeanPostProcessor
                        boolean matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        //此处省略若干方法      
                        if (matchFound) {
                            result.add(beanName);
                        }
                //此处省略若干方法
                }
                return StringUtils.toStringArray(result);
            }
        }   
      

    可以发现它最终还是需要通过遍历Spring容器中所有的beanName才能够将这个bean注册为BeanProcessor 如果这个BeanPostProcessor的实现类都没有被Spring托管 也就不可能被注册为beanProcessor 这也就是为什么beanProcessor的实现类必须被spring托管才能生效。

    三、BeanPostProcessor执行的流程

    //第一步 容器刷新
    1、AbstractApplicationContext.refresh()
    //第二步 完成beanFactory初始化
    2、AbstractApplicationContext.finishBeanFactoryInitialization(beanFactory);  
    //第三步 默认的beanFactory开始预实例化单例bean
    3、DefaultListableBeanFactory.preInstantiateSingletons();
    //第四步 开始根据bean的名称获取bean
    4、AbstractBeanFactory.getBean(String name);
    //第五步 执行doCreateBean方法 开始创建bean
    5、AbstractAutowireCapableBeanFactory.doCreateBean()
    //第六步 对bean进行初始化
    AbstractAutowireCapableBeanFactory.initializeBean()  
    //第七步 开始遍历beanProcessor 执行beanProcessor的postProcessBeforeInitialization方法
    AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization();
    //第八步 执行beanPostProcessor的后置方法
    AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization();
    

    initializeBean源码

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
            //此处省略若干方法
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
          //执行beanPostProcessor的前置方法
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
    
            try {
          //执行bean的初始化方法
                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()) {
          //执行beanPostProcessor的后置方法
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
    
            return wrappedBean;
        }
    

    applyBeanPostProcessorsBeforeInitialization源码

    @Override
        public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
                throws BeansException {
    
            Object result = existingBean;
        //遍历beanPostProcessor 执行前置方法
            for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessBeforeInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }
    

    applyBeanPostProcessorsAfterInitialization源码

    @Override
        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {
    
            Object result = existingBean;
            for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }
    

    相关文章

      网友评论

        本文标题:Spring BeanPostProsser最佳实践

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