【Spring注解驱动开发】在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean

写在前面

在前面的文章中,咱们学习了如何使用@Import注解向Spring容器中导入bean,可使用@Import注解快速向容器中导入bean,小伙伴们能够参见《【Spring注解驱动开发】使用@Import注解给容器中快速导入一个组件》。能够在@Import注解中使用ImportSelector接口导入bean,小伙伴们能够参见《【Spring注解驱动开发】在@Import注解中使用ImportSelector接口导入bean》一文。今天,咱们就来讲说,如何在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean。java

项目工程源码已经提交到GitHub:https://github.com/sunshinelyz/spring-annotationgit

ImportBeanDefinitionRegistrar概述

概述

咱们先来看看ImportBeanDefinitionRegistrar是个什么鬼,点击进入ImportBeanDefinitionRegistrar源码,以下所示。github

package org.springframework.context.annotation;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.type.AnnotationMetadata;

public interface ImportBeanDefinitionRegistrar {

	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
			BeanNameGenerator importBeanNameGenerator) {

		registerBeanDefinitions(importingClassMetadata, registry);
	}

	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	}

}

由源码能够看出,ImportBeanDefinitionRegistrar本质上是一个接口。在ImportBeanDefinitionRegistrar接口中,有一个registerBeanDefinitions()方法,经过registerBeanDefinitions()方法,咱们能够向Spring容器中注册bean实例。spring

Spring官方在动态注册bean时,大部分套路实际上是使用ImportBeanDefinitionRegistrar接口。bash

全部实现了该接口的类都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,因此ImportBeanDefinitionRegistrar中动态注册的bean是优先于依赖其的bean初始化的,也能被aop、validator等机制处理。微信

使用方法

ImportBeanDefinitionRegistrar须要配合@Configuration和@Import注解,@Configuration定义Java格式的Spring配置文件,@Import注解导入实现了ImportBeanDefinitionRegistrar接口的类。框架

ImportBeanDefinitionRegistrar实例

既然ImportBeanDefinitionRegistrar是一个接口,那咱们就建立一个MyImportBeanDefinitionRegistrar类,实现ImportBeanDefinitionRegistrar接口,以下所示。ide

package io.mykit.spring.plugins.register.condition;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author binghe
 * @version 1.0.0
 * @description ImportBeanDefinitionRegistrar的实现类
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata: 当前类的注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类
     * 经过调用BeanDefinitionRegistry接口的registerBeanDefinition()方法,能够将全部须要添加到容器中的bean注入到容器中。
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){

    }
}

能够看到,这里,咱们先建立了MyImportBeanDefinitionRegistrar类的大致框架。接下来,咱们在PersonConfig2类上的@Import注解中,添加MyImportBeanDefinitionRegistrar类,以下所示。学习

@Configuration
@Import({Department.class, Employee.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class PersonConfig2 {

接下来,建立一个Company类,做为测试测试ImportBeanDefinitionRegistrar接口的bean,以下所示。测试

package io.mykit.spring.plugins.register.bean;

/**
 * @author binghe
 * @version 1.0.0
 * @description 测试ImportBeanDefinitionRegistrar接口的使用
 */
public class Company {
}

接下来,就要实现MyImportBeanDefinitionRegistrar类中的registerBeanDefinitions()方法的逻辑了,添加逻辑后的registerBeanDefinitions()方法以下所示。

/**
     * AnnotationMetadata: 当前类的注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类
     * 经过调用BeanDefinitionRegistry接口的registerBeanDefinition()方法,能够将全部须要添加到容器中的bean注入到容器中。
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
        boolean employee = registry.containsBeanDefinition("employee");
        boolean department = registry.containsBeanDefinition("department");
        if (employee && department){
            BeanDefinition beanDefinition = new RootBeanDefinition(Company.class);
            registry.registerBeanDefinition("company", beanDefinition);
        }
    }

registerBeanDefinitions()方法的实现逻辑很简单,就是判断Spring容器中是否同时存在以employee命名的bean和以department命名的bean,若是同时存在以employee命名的bean和以department命名的bean,则向Spring容器中注入一个以company命名的bean。

接下来,咱们就运行SpringBeanTest类中的testAnnotationConfig7()方法来进行测试,输出结果信息以下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001

能够看到,在输出结果中,并无看到“company”,这是由于输出结果中存在io.mykit.spring.plugins.register.bean.Department和io.mykit.spring.plugins.register.bean.Employee,并不存在咱们代码逻辑中的department和employee。因此,咱们将registerBeanDefinitions()方法的逻辑稍微修改下,修改后的代码以下所示。

/**
  * AnnotationMetadata: 当前类的注解信息
  * BeanDefinitionRegistry:BeanDefinition注册类
  * 经过调用BeanDefinitionRegistry接口的registerBeanDefinition()方法,能够将全部须要添加到容器中的bean注入到容器中。
  */
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
    boolean employee = registry.containsBeanDefinition(Employee.class.getName());
    boolean department = registry.containsBeanDefinition(Department.class.getName());
    if (employee && department){
        BeanDefinition beanDefinition = new RootBeanDefinition(Company.class);
        registry.registerBeanDefinition("company", beanDefinition);
    }
}

接下来,咱们再次运行SpringBeanTest类中的testAnnotationConfig7()方法来进行测试,输出结果信息以下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
io.mykit.spring.plugins.register.bean.User
io.mykit.spring.plugins.register.bean.Role
person
binghe001
company

能够看到,此时输出了company,说明Spring容器中已经成功注册了以company命名的bean。

好了,我们今天就聊到这儿吧!别忘了给个在看和转发,让更多的人看到,一块儿学习一块儿进步!!

项目工程源码已经提交到GitHub:https://github.com/sunshinelyz/spring-annotation

写在最后

若是以为文章对你有点帮助,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习Spring注解驱动开发。公众号回复“spring注解”关键字,领取Spring注解驱动开发核心知识图,让Spring注解驱动开发再也不迷茫。

相关文章
相关标签/搜索