spring动态注册bean

隔壁王叔叔
2018-03-22 / 0 评论 / 80 阅读 / 正在检测是否收录...
某些情况下静态的配置信息无法满足系统需求,需要根据静态配置动态生成bean注册到spring中。

为啥要动态注册bean?#

某些情况下静态的配置信息无法满足系统需求,需要根据静态配置动态生成bean注册到spring中。在写一些工具的时候会用到的,原本打算写一个类似 Fegin 的小组件。于是有了这个研究动机。但后来网上找到了我想要的开源项目,就不重复造轮子了,但是技术点还是研究了一下。 感兴趣的可以去看看这个项目:Forest

啥时候注册bean?#

太晚了肯定不行啊,@Autowired不等人,在Autowired注入之后注册肯定报错啊,想都不要想。那么就要在Autowired之前。

咋注册呢?#

Spring 通过一个 BeanPostProcessor 对 @Autowired 进行解析,所以要让 @Autowired 起作用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。

  1. 思路一

    搞一个类实实现BeanPostProcessor,ApplicationContextAware接口 让它早于AutowiredAnnotationBeanPostProcessor运行。BeanPostProcessor,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。but这个我没搞出来不知的问题出在哪里,有机会再研究研究。

  2. 思路二

    搞一个类实现BeanFactoryPostProcessor接口.这是个啥接口呢?实现该接口,可以在spring的bean创建之前,修改bean的定义属性。不废话直接贴代码。

    public class MyBeanFactoryPostProcessor implements ApplicationContextAware,  BeanFactoryPostProcessor {  
        
        private static ApplicationContext applicationContext;  
    
        private String packageS;
        
        public String getPackageS() {
            return packageS;
        }
    
        public void setPackageS(String packageS) {
            this.packageS = packageS;
        }
    
        @Override  
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
            MyBeanFactoryPostProcessor.applicationContext = applicationContext;  
        }  
      
        public static ApplicationContext getApplicationContext() {  
            return applicationContext;  
        }  
        public static Object getBean(String beanName) {  
            return applicationContext.getBean(beanName);  
        }  
          
        public static <T>T getBean(String beanName , Class<T>clazz) {  
            return applicationContext.getBean(beanName , clazz);  
        }  
        
        /**
         * 此方法会在bean初始化完成但未实例化时调用
         */
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)  
                throws BeansException {  
            //beanFactory 也可以拿到当前系统从已经初始化好的bean,也可以做一些修改
            //设置了扫描路径则则可以根据扫描包扫描相应的注解
            System.out.println("packageS==================="+packageS);
            //获取BeanFactory
            DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
            //模拟扫描到的bean,用动态代理等等方式创建    
            //创建bean信息.
            BeanDefinitionBuilder beanDefinitionBuilder =BeanDefinitionBuilder.genericBeanDefinition(RestBean.class);
            beanDefinitionBuilder.addPropertyValue("name","张三");
            //动态注册bean.
            defaultListableBeanFactory.registerBeanDefinition("restBean",beanDefinitionBuilder.getBeanDefinition());
            //注册进spring上下文的bean可以获取一下看看
            BeanDefinition bd = beanFactory.getBeanDefinition("restBean");  
        } 
      
    } 
    

    javaConfig

    @Configuration
    public class Config {
        
        @Bean
        public MyBeanFactoryPostProcessor getMyBeanFactoryPostProcessor() {
            MyBeanFactoryPostProcessor sss = new MyBeanFactoryPostProcessor();
            sss.setPackageS("com.xxxx");
            return sss;
        }
        
    }
    

    现在就可以在spring管理的任何类中使用了

      @Autowired
      RestBean restBean;

    代码地址:BeanLoad

    知乎上看到一个专栏,学到不少东西。有兴趣可以关注一下。晓风轻

0

评论 (0)

取消