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

相关推荐
码少女10 小时前
Linux--多路转接之select
java·服务器·数据库
一个风轻云淡10 小时前
Markdown学习与实践
后端
程序员cxuan10 小时前
真没想到,AI 圈又杀出来一匹黑马!
人工智能·后端·程序员
nvvas11 小时前
Java 入门(四):数组——数据的集合管理
java·开发语言
掘金者阿豪11 小时前
极空间 NAS 部署 Typecho:从 Docker 安装、主题配置到固定公网访问
后端
科技苑11 小时前
前后端分离与微服务架构如何协同?
前端·后端·前端框架
Lambert28111 小时前
AgentScope Java 从零(07):官方有权限引擎,我却在工具里写了个 if
java·后端·ai编程
Ticnix11 小时前
多租户 RAG:让每个用户只检索到自己的知识库
后端·python·agent
ID346107442011 小时前
【课程设计】基于Spring Boot+Vue的游戏账号租赁系统的设计与实现-计算机毕设 附源码50345
javascript·vue.js·spring boot·python·node.js·php·课程设计
Kyrie_kk11 小时前
Java--ThreadLocal线程副本(一)
java·后端