首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringBoot基础(四):注册Bean的八种方式及适用场景

SpringBoot基础(四):注册Bean的八种方式及适用场景

作者头像
Java微观世界
发布2025-06-13 11:06:38
发布2025-06-13 11:06:38
72500
代码可运行
举报
文章被收录于专栏:springbootspringboot
运行总次数:0
代码可运行
一、@Component及其派生注解

实现方式

在类上添加@Component@Service@Controller@Repository等注解,配合@ComponentScan扫描包路径。

适用场景

  • 常规业务组件(如Service层、Controller层等)
  • 需要Spring自动扫描并管理的类

示例

代码语言:javascript
代码运行次数:0
运行
复制
@Service
public class UserService {
    // 业务逻辑
}

二、@Bean注解

实现方式

在配置类(@Configuration标记的类)中,通过@Bean标注方法,返回对象实例。

适用场景

  • 引入第三方库的类(如数据库连接池、工具类)
  • 需要自定义初始化逻辑的Bean

示例

  • 方法名默认为Bean的唯一标识
代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
public class MyConfig {
    @Bean
    public User user() {
        return new User("Marry", 12345L);
    }
}

三、@Import注解导入
1、导入其他配置类或普通类

实现方式

在配置类中使用@Import导入其他配置类普通类,使其成为Bean。

适用场景

  • 模块化配置(如将多个配置类分散管理,根据需要组合它们)
  • 快速注册单个Bean,,等同于在类上标注@Component

示例

代码语言:javascript
代码运行次数:0
运行
复制
// 安全模块配置
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilter securityFilter() {
        return new SecurityFilter();
    }
}
// 数据访问模块配置
@Configuration
public class DataAccessConfig {
    @Bean
    public Repository repository() {
        return new JpaRepository();
    }
}

// 无特殊注解
public class BeanD {
}

// 主配置类
@Configuration
@Import({SecurityConfig.class, DataAccessConfig.class, BeanD.class})
public class ApplicationConfig {
    @Bean
    public MyService myService() {
    	// 可以使用DataAccessConfig中的bean
        return new MyService(repository()); 
    }
}

2、使用ImportSelector进行动态导入

实现方式

需创建实现ImportSelector接口的类,并重写selectImports()方法返回需注册的类全限定名数组

适用场景

  • 结合@Conditional等注解,可在selectImports()中根据条件(如配置属性、环境变量)动态返回不同的类名数组,实现按需加载
  • 如SpringBoot的@EnableAutoConfiguration通过AutoConfigurationImportSelector加载spring.factories中的自动配置类

示例

  • AnnotationMetadata参数可获取导入类的注解、接口、父类等信息(如@EnableXXX的配置),用于更复杂的逻辑判断
  • 如下则是判断MyCofig类上有@Configuration注解则加载Dog类,否则加载Cat类
代码语言:javascript
代码运行次数:0
运行
复制
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
        System.out.println("元数据Class名称:" + metadata.getClassName());
        //各种条件的判定,判定完毕后,决定是否装载指定的bean
        boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Configuration");
        if(flag){
            return new String[]{"com.xc.springboot.bean.Dog"};
        }
        return new String[]{"com.xc.springboot.bean.Cat"};
    }
}

// 使用方式
@Configuration
@Import(MyImportSelector.class)
public class MyConfig {
}

3、使用ImportBeanDefinitionRegistrar进行更灵活的控制

实现方式

需创建实现ImportBeanDefinitionRegistrar接口的类,并重写registerBeanDefinitions()方法通过BeanDefinitionRegistry动态注册Bean

适用场景

  • 根据环境变量、类路径是否存在类等条件动态注册Bean
  • MyBatisMapper扫描等,利用该机制动态生成代理类

示例

  • 通过@EnableMyFeature注解触发ImportBeanDefinitionRegistrar实现类,‌根据环境变量条件动态注册MyServiceImpl的Bean到Spring容器‌,实现灵活的编程式配置
代码语言:javascript
代码运行次数:0
运行
复制
// 1.自定义注解@EnableMyFeature‌
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyFeatureRegistrar.class) // 关联注册实现类
public @interface EnableMyFeature {
    String value() default "";
}

// 2.实现ImportBeanDefinitionRegistrar‌
public class MyFeatureRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        // 读取@EnableMyFeature注解的属性
        Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableMyFeature.class.getName());
        String value = (String) attrs.get("value");

        // 示例:根据环境变量决定是否注册Bean
        boolean isEnabled = environment.getProperty("my.feature.enabled", Boolean.class, false);
        if (isEnabled) {
            BeanDefinition beanDef = BeanDefinitionBuilder
                .genericBeanDefinition(MyServiceImpl.class)
                .addPropertyReference("dependency", "myDependency")
                .getBeanDefinition();
            registry.registerBeanDefinition("myService", beanDef);
        }
    }
}


// 3.在配置类中使用@EnableMyFeature‌
@Configuration
@EnableMyFeature("customValue") // 触发MyFeatureRegistrar的执行
public class AppConfig {
    // 其他Bean定义...
}

4、ImportSelector 与 ImportBeanDefinitionRegistrar‌区别

对比维度

ImportSelector

ImportBeanDefinitionRegistrar

核心目的

动态返回需要导入的‌配置类全限定名

直接通过代码向容器‌注册Bean定义‌

使用场景

基于‌类的导入‌,适用于批量配置加载

基于‌Bean 定义的编程式注册‌,适用底层扩展,动态注册复杂Bean定义

执行时机

在配置类解析阶段执行

在 Bean 定义注册阶段执行

灵活性

通过间接导入类实现批量配置加载

直接操作 Bean 定义,支持更细粒度的控制(如属性注入、条件判断)

依赖的输入参数

接收 AnnotationMetadata(当前 @Import 注解的元数据)

接收 AnnotationMetadata 和 BeanDefinitionRegistry(可直接操作容器)

与配置类的关系

依赖返回的配置类中的 @Bean 方法或 @Import 进一步注册 Bean

不依赖配置类,直接注册 Bean 定义,甚至可注册非 @Configuration 类中的 Bean

四、FactoryBean接口实现

实现方式

实现FactoryBean接口,重写getObject()方法定义Bean实例,并通过@Component@Bean注册接口实现类

适用场景

  • 复杂对象的创建(如MyBatis的SqlSessionFactoryBean
  • 需要延迟初始化或条件创建的Bean

示例

  • ⚠️容器中实际注册的是getObject()返回的对象,而非FactoryBean本身
代码语言:javascript
代码运行次数:0
运行
复制
@Component
public class DogFactoryBean implements FactoryBean<Dog> {
    //创建bean的复杂过程
    @Override
    public Dog getObject() throws Exception {
        Dog d = new Dog();
        //.........
        return d;
    }
    //bean的类型
    @Override
    public Class<?> getObjectType() {
        return Dog.class;
    }
    //bean是否单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}

五、编程式注册(ApplicationContext)

实现方式

通过ApplicationContextBeanFactory直接注册Bean。

适用场景

  • 在运行时动态添加Bean

示例

代码语言:javascript
代码运行次数:0
运行
复制
public class App {
	public static void main(String[] args) {
	    SpringApplication.run(App.class, args)
	        .getBeanFactory()
	        .registerSingleton("customBean", new CustomBean());
	}
}

六、自动配置(spring.factories)‌

实现方式

通过META-INF/spring.factories声明自动配置类,结合@Conditional实现按需装配。

适用场景

  • 开发自定义Starter
  • 封装通用模块供多个项目复用

示例

代码语言:javascript
代码运行次数:0
运行
复制
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xc.MyAutoConfiguration
代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
public class MyAutoConfiguration {
    @Bean
    public MyBean myBean() { ... }
}

七、@ImportResource注解导入XML配置

实现方式

在XML文件中通过<bean>标签定义Bean,并在配置类中使用@ImportResource导入XML文件。

适用场景

  • 旧系统迁移或集成遗留XML配置
  • 需要与Spring Boot注解配置混合使用

示例

代码语言:javascript
代码运行次数:0
运行
复制
<!-- beans.xml -->
<bean id="xmlUser" class="com.example.User" />
代码语言:javascript
代码运行次数:0
运行
复制
@ImportResource("classpath:beans.xml")
@Configuration
public class XmlConfig { ... }

八、动态注册:BeanDefinitionRegistryPostProcessor

实现方式

实现BeanDefinitionRegistryPostProcessor接口,在postProcessBeanDefinitionRegistry()方法中手动注册BeanDefinition

适用场景

  • 框架开发中动态注册Bean(如Spring Boot Starter自动配置)
  • 根据运行时条件(如配置文件、环境变量)‌决定是否注册Bean

示例

  • 可以在Bean实例化前修改容器元信息
代码语言:javascript
代码运行次数:0
运行
复制
@Component
public class DynamicRegistrar implements BeanDefinitionRegistryPostProcessor {
	// 注册Bean定义(先执行)
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        BeanDefinition definition = BeanDefinitionBuilder
                .genericBeanDefinition(User.class)
                .addPropertyValue("name", "DynamicUser")
                .getBeanDefinition();
        registry.registerBeanDefinition("dynamicUser", definition);
    }

	// 修改Bean定义(后执行-加载所有Bean定义之后、Bean实例化之前)
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 在这里可以对 BeanFactory 进行进一步的配置
        System.out.println("Bean factory post-processing");
    }
}

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、@Component及其派生注解
  • 二、@Bean注解
  • 三、@Import注解导入
    • 1、导入其他配置类或普通类
    • 2、使用ImportSelector进行动态导入
    • 3、使用ImportBeanDefinitionRegistrar进行更灵活的控制
    • 4、ImportSelector 与 ImportBeanDefinitionRegistrar‌区别
  • 四、FactoryBean接口实现
  • 五、编程式注册(ApplicationContext)
  • 六、自动配置(spring.factories)‌
  • 七、@ImportResource注解导入XML配置
  • 八、动态注册:BeanDefinitionRegistryPostProcessor
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档