美文网首页技术笔记
Spring动态替换Bean

Spring动态替换Bean

作者: Sanisy | 来源:发表于2018-09-14 11:10 被阅读960次

    BeanPostProcessor是创建每个类时都会去执行的一个接口,postProcessBeforeInitialization是在类初始化之前调用的一个方法,创建的对象的引用会指向改方法的返回值对象。调用过程示例如下:

    ClassA classA = new ClassA();
    classA = postProcessBeforeInitialization(classA, "classA");
    

    所以我们可以通过该方法就可以实现动态替换我们的bean。

    package com.example.hellododo.data;
    
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.stereotype.Component;
    
    /**
     * @author Liangzhifeng
     * date: 2018/9/4
     */
    @Slf4j
    @Component
    public class LocalProcessor implements BeanPostProcessor {
    
        @Autowired
        private DefaultListableBeanFactory defaultListableBeanFactory;
    
        private String targetBeanName = "test22";
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (StringUtils.endsWithIgnoreCase(beanName, targetBeanName)) {
                boolean containsBean = defaultListableBeanFactory.containsBean(targetBeanName);
                if (containsBean) {
                    //移除bean的定义和实例
                    defaultListableBeanFactory.removeBeanDefinition(targetBeanName);
                }
                //注册新的bean定义和实例
                defaultListableBeanFactory.registerBeanDefinition(targetBeanName, BeanDefinitionBuilder.genericBeanDefinition(Test55.class).getBeanDefinition());
                bean = null;
                return new Test55();
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
    

    在事件监听器中,分别注入和获取Bean对象。分别打印两个对象的类名,可以看到两个类名都是com.example.hellododo.data.Test55

    package com.example.hellododo.data;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.event.ContextRefreshedEvent;
    import org.springframework.stereotype.Component;
    
    /**
     * @author Liangzhifeng
     * date: 2018/9/12
     */
    @Slf4j
    @Component
    public class LocalEventListener implements ApplicationListener<ContextRefreshedEvent> {
    
        @Autowired
        private DefaultListableBeanFactory defaultListableBeanFactory;
    
        private boolean doFist = true;
    
        @Autowired
        private Test22 test22;
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
    
            Test22 bean = defaultListableBeanFactory.getBean(Test22.class);
            if (doFist) {
                if (bean != null) {
                    log.info("autowiredClassName={}, beanClassName={}", test22.getClass().getName(), bean.getClass().getName());
                    doFist = false;
                }
            }
        }
    }
    
    
    package com.example.hellododo.data;
    
    import lombok.Data;
    
    /**
     * @author Liangzhifeng
     * date: 2018/9/6
     */
    @Data
    public class Test {
    
        private String data;
    }
    
    @Component
    package com.example.hellododo.data;
    
    import org.springframework.stereotype.Component;
    
    /**
     * @author Liangzhifeng
     * date: 2018/9/6
     */
    @Component
    public class Test22 extends Test{
    
    }
    
    package com.example.hellododo.data;
    
    /**
     * @author Liangzhifeng
     * date: 2018/9/6
     */
    public class Test55 extends Test22{
      
    }
    

    相关文章

      网友评论

        本文标题:Spring动态替换Bean

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