动态注册bean,Spring官方套路:使用BeanDefinitionRegistryPostProcessor

动态注册bean,Spring官方套路:使用BeanDefinitionRegistryPostProcessor

之前写过关于Spring总动态注册Bean的两篇文章

Spring动态注册bean
动态注册bean,Spring官方套路:使用ImportBeanDefinitionRegistrar

这里再介绍一个Spring官方大量使用的接口BeanDefinitionRegistryPostProcessor,这个接口扩展自BeanFactoryPostProcessor,专门用于动态注册Bean。
此外,Spring5中的BeanDefinitionBuilder还增加了一个新的genericBeanDefinition方法,签名如下:

public static <T> BeanDefinitionBuilder genericBeanDefinition(
			@Nullable Class<T> beanClass, Supplier<T> instanceSupplier)


可以看到,此处在会用Supplier接口的返回值作为bean的实例。
这样就提供了替代传统的static和instance factory-mehtod的功能,前面两者分别需要调用BeanDefinitionBuilder#setFactoryMethodBeanDefinitionBuilder#setFactoryMethodOnBean专门进行配置。


因为这里要使用Spring5,所以Spring Boot要使用2.x版本,编写该文章时,最新版本为2.0.0.M5,该依赖并没有发布到maven中央仓库中,需要手工添加Spring的仓库,如下:

...省略
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.M5</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<repositories>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/snapshot</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

<pluginRepositories>
    <pluginRepository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/snapshot</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </pluginRepository>
    <pluginRepository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
</pluginRepositories>    

...省略

核心代码如下:

@Component
@Slf4j
public class PersonBeanDefinitionRegistryPostProcessor
		implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
    throws BeansException {
        // 注册Bean定义,容器根据定义返回bean
        log.info("register personManager1>>>>>>>>>>>>>>>>");
        //构造bean定义
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
				.genericBeanDefinition(PersonManager.class);
        //设置依赖
        beanDefinitionBuilder.addPropertyReference("personDao", "personDao");
        BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder
				.getRawBeanDefinition();
        //注册bean定义
        registry.registerBeanDefinition("personManager1", personManagerBeanDefinition);

	}

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
    throws BeansException {
        // 注册Bean实例,使用supply接口
        log.info("register personManager2>>>>>>>>>>>>>>>>");
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
            .genericBeanDefinition(PersonManager.class, () -> {
	         PersonDao personDao = beanFactory.getBean(PersonDao.class);
                 PersonManager personManager = new PersonManager();
                 personManager.setPersonDao(personDao);
                 return personManager;
         });
         BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder
            .getRawBeanDefinition();
        ((DefaultListableBeanFactory) beanFactory)
          .registerBeanDefinition("personManager2", personManagerBeanDefinition);
    }
}

完整代码:github.com/pkpk1234/Bea

官方例子:
Spring ConfigurationClassPostProcessor

Spring Cloud RefreshAutoConfigurationGenericScope



编辑于 2017-10-30

文章被以下专栏收录