Spring Boot框架,类注入成 Bean的方式

在 Spring Boot 中,将一个类注入成 Bean(即交由 Spring 容器管理)主要有以下几种方式:

方式 适用场景 优点 缺点
@Component 系列 自己写的类 简单快捷 侵入性强
@Bean 第三方类、配置类 灵活、无侵入 需要配置类
@Import 动态导入、模块化 批量导入方便 理解成本稍高
FactoryBean 复杂创建逻辑 高度定制 代码较多
@Conditional 条件注册 灵活控制 增加复杂度

1. @Component 系列注解

最常用的方式,在类上直接添加注解。

java 复制代码
// @Component 通用注解
@Component
public class UserService {
    public void doSomething() {
        System.out.println("UserService doing something");
    }
}

// @Service 业务层专用
@Service
public class OrderService {
    public void createOrder() {
        System.out.println("Order created");
    }
}

// @Repository 数据访问层专用
@Repository
public class UserRepository {
    public void save() {
        System.out.println("User saved");
    }
}

// @Controller / @RestController Web层专用
@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello";
    }
}

2. @Bean 配合 @Configuration

适用于第三方类或需要自定义初始化逻辑的 Bean。

java 复制代码
@Configuration
public class AppConfig {
    
    // 注册第三方类
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    // 带初始化/销毁方法的 Bean
    @Bean(initMethod = "init", destroyMethod = "cleanup")
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        ds.setUsername("root");
        ds.setPassword("123456");
        return ds;
    }
    
    // 依赖其他 Bean
    @Bean
    public UserService userService(OrderService orderService) {
        return new UserService(orderService);
    }
}

3. @Import 注解

导入特定类作为 Bean,适用于无法修改源码的类。

java 复制代码
// 方式1:直接导入类
@Import({ExternalService.class, HelperUtil.class})
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// 方式2:导入 ImportSelector
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
        return new String[]{"com.example.ServiceA", "com.example.ServiceB"};
    }
}

@Import(MyImportSelector.class)
@SpringBootApplication
public class Application { }

// 方式3:导入 ImportBeanDefinitionRegistrar(更灵活的注册)
public class MyBeanRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, 
                                       BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder
            .genericBeanDefinition(UserService.class)
            .addPropertyValue("name", "test");
        registry.registerBeanDefinition("userService", builder.getBeanDefinition());
    }
}

4. FactoryBean 接口

用于创建复杂对象的 Bean。

java 复制代码
@Component
public class MyBeanFactory implements FactoryBean<UserService> {
    
    @Override
    public UserService getObject() throws Exception {
        // 复杂的创建逻辑
        UserService userService = new UserService();
        userService.setName("Created by FactoryBean");
        return userService;
    }
    
    @Override
    public Class<?> getObjectType() {
        return UserService.class;
    }
    
    @Override
    public boolean isSingleton() {
        return true; // 单例模式
    }
}

5. @ComponentScan 自定义扫描路径

指定 Spring 扫描哪些包下的注解类。

java 复制代码
@SpringBootApplication
@ComponentScan(basePackages = {"com.example.service", "com.example.repository"})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

6. 实现 InitializingBeanBeanPostProcessor

在 Bean 注册后进行额外处理(较少用于注册本身)。

java 复制代码
@Component
public class CustomBean implements InitializingBean {
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Bean 初始化完成");
        // 可以在此做额外配置
    }
}

7. 条件化注册 @Conditional

根据条件决定是否注册 Bean。

java 复制代码
@Configuration
public class ConditionalConfig {
    
    @Bean
    @ConditionalOnMissingBean  // 不存在时才创建
    public UserService userService() {
        return new UserService();
    }
    
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new RedisCacheManager();
    }
    
    @Bean
    @ConditionalOnClass(name = "com.mysql.jdbc.Driver")
    public DataSource mysqlDataSource() {
        return new MysqlDataSource();
    }
}

实际开发中最常用的是前两种 :自己写的类用 @Service/@Component,第三方类或需要配置的类用 @Bean

相关推荐
倔强的石头_3 分钟前
从5万次到日均2000万次调用:大模型推理服务的性能工程实践V2.1
后端
tachibana218 分钟前
hot100 翻转二叉树(226)
java·数据结构·算法·leetcode
brave_zhao24 分钟前
nginx的进程架构
java·学习·nginx
兰令水24 分钟前
leecodecode【面试150】【2026.7.9打卡-java版本】
java·数据结构·leetcode·面试·职场和发展
禾高网络28 分钟前
互联网医院|AI 互联网医院成品开发系统
java·大数据·人工智能·小程序
环境栈笔记30 分钟前
多账号浏览器选型检查清单:Profile、权限、Session 和任务日志怎么评估
前端·人工智能·后端·自动化
shepherd11135 分钟前
一次把 Spring MVC 文件上传参数“查没了”的排查:multipart、Filter 与 request body 的连环坑
java·spring boot·后端
lbb 小魔仙38 分钟前
MuMu 模拟器 6.0 硬核测评:这次升级确实不一样
java·开发语言·模拟器·mumu·硬核测评
前端炒粉39 分钟前
手写promise
java·前端·javascript
mONESY1 小时前
Node.js fs 文件系统模块 四种读写方案全解析
javascript·后端