基于ImportBeanDefinitionRegistrar和FactoryBean动态注入Bean到Spring容器中

网友投稿 240 2022-09-26

基于ImportBeanDefinitionRegistrar和FactoryBean动态注入Bean到Spring容器中

基于ImportBeanDefinitionRegistrar和FactoryBean动态注入Bean到Spring容器中

​​一、背景​​​​二、实现方案​​

​​1、基于@ComponentScan注解实现​​​​2、基于ImportBeanDefinitionRegistrar和FactoryBean实现​​​​3、注意​​

​​三、实现步骤​​

​​1、自定义注解`CustomImport`​​​​2、实现`CustomImportFactoryBean`构建对象​​​​3、编写`ImportBeanDefinitionRegistrar`​​​​4、编写@EnableCustomImport​​​​5、运行一个小的案例,获取测试结果​​

​​四、完成代码​​​​五、参考链接​​

一、背景

我们自己开发了一个第三方的jar包,想和Spring整合起来,并注入到Spring容器中。自己的jar包中,需要加入到Spring容器的类上都加入了一个自定义注解​​@CustomImport(beanName="")​​​,​​beanName​​属性的值表示需要注入到Spring容器中的名字。

二、实现方案

1、基于@ComponentScan注解实现

使用此种方案比较简单,直接使用​​@ComponentScan(includeFilters = {@ComponentScan.Filter(value = CustomImport.class)})​​即可将我们自定义的注解加入到Spring容器中。 此种方案略。

2、基于ImportBeanDefinitionRegistrar和FactoryBean实现

1、实现此接口(​​ImportBeanDefinitionRegistrar​​​),可以将我们自己的​​BeanDefinition​​​对象加到​​BeanDefinitionRegistry​​中,等待后续Spring初始化对象。

注:

1. 我们可以从自定义的注解中获取到一些属性,然后来个性化我们要初始化的Bean是什么样的。

​ 2. 实现​​ImportBeanDefinitionRegistrar​​​的类配合上​​@Configuration​​​和​​@Import​​注解,可以在程序启动的时候加载这个类。

2、实现此接口(​​FactoryBean​​),可以让我们自定义实例化出我们要构建的Bean。

3、注意

可能有些人会说,我用@ComponentScan就可以搞定的事情,为何还要选择基于第二种方法实现,这个不是多此一举吗?这个其实我主要是记录这样的一个思路。比如:Mybatis和Spring整合后,只需要申明一个​​@Mapper​​​就可以自定加入到Spring管理中(​​MapperScannerRegistrar​​),那么这是怎么实现的呢?应该是和上方的方案2类似。

三、实现步骤

1、自定义一个注解 ​​CustomImport​​,被此注解标注的类,表示需要加入到Spring容器中。

CustomImport 注解可以增加一些额外的属性,比如beanName表示注入到Spring容器时,bean的名字。

2、写一个类实现​​CustomImportFactoryBean​​​,表示如何实例化出​​CustomImport​​注解标注的类。

构造化对象。构造出的对象需要自己完成初始化操作,如果需要用到Spring的里的对象,可以获取到ApplicationContext然后获取注入。

3、写一个类实现​​ImportBeanDefinitionRegistrar​​​,扫描出所有的​​CustomImport​​​的类,然后构造出​​BeanDefinition​​,加入到Spring容器中。

构造BeanDefinition时的BeanClass属性需要指定上一个的CustomImportFactoryBean的class。ClassPathBeanDefinitionScanner可以扫描包。

4、自定义一个注解​​EnableCustomImport​​​,启动类上加入此注解后,实现​​ImportBeanDefinitionRegistrar​​的调用。

此注解上需要使用​​@Import​​标注

1、自定义注解​​CustomImport​​

/** * 此注解标注的类也会自动加入到 Spring 管理中。 * * @author huan.fu 2021/4/14 - 上午9:23 */@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface CustomImport { /** * 这个bean注入到Spring容器中的名字 */ String beanName();}

2、实现​​CustomImportFactoryBean​​构建对象

package com.huan.study.framewrok;import org.springframework.beans.BeansException;import org.springframework.beans.factory.FactoryBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;/** * 工厂Bean,用于构建 CustomImport 注解标注的类,如何进行实例化 * * @author huan.fu 2021/4/14 - 上午9:44 */public class CustomImportFactoryBean implements FactoryBean, ApplicationContextAware { private Class type; private String beanName; private ApplicationContext applicationContext; /** * 此处构建的对象,如果需要依赖Spring Bean的话,需要自己构建进去,默认不会自动注入,即默认情况下@Autowired注解不生效 */ @Override public Object getObject() throws Exception { Object instance = this.type.getDeclaredConstructor().newInstance(); applicationContext.getAutowireCapableBeanFactory().autowireBean(instance); return instance; } @Override public Class getObjectType() { return type; } public Class getType() { return type; } public void setType(Class type) { this.type = type; } public String getBeanName() { return beanName; } public void setBeanName(String beanName) { this.beanName = beanName; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}

3、编写​​ImportBeanDefinitionRegistrar​​

4、编写@EnableCustomImport

/** * 启用自动导入 * * @author huan.fu 2021/4/14 - 上午9:29 */@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Import(CustomImportBeanDefinitionRegistrar.class)public @interface EnableCustomImport { String[] packages() default {};}

5、运行一个小的案例,获取测试结果

四、完成代码

1、​​https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/bean-definition-registrar​​

五、参考链接

1、​​https://stackoverflow.com/questions/4970297/how-to-get-beans-created-by-factorybean-spring-managed​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:英特尔、高通、三星、索尼等申请为华为供芯片:批下来或要超1年!
下一篇:微信小程序 scroll-view 完成上拉加载更多
相关文章

 发表评论

暂时没有评论,来抢沙发吧~