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

相关推荐
铁皮饭盒8 小时前
bun 和 pnpm 谁硬? 谁软?
前端·后端
用户8356290780518 小时前
使用 Python 创建 Excel 雷达图
后端·python
程序员cxuan8 小时前
还在用 xigh 拉满跑?大错特错
人工智能·后端·程序员
城管不管8 小时前
什么是Prompt?
android·java·数据库·语言模型·llm·prompt
AI大模型8 小时前
被AI抢饭碗的Java程序员,后来都怎样了?
java·后端·ai编程
苦逼的猿宝8 小时前
医院管理系统.(源码+论文)
java·毕业设计·springboot·计算机毕业设计
東雪木8 小时前
JVM 与 Java 内存模型 专属复习笔记
java·jvm·笔记·java面试
爱睡觉1118 小时前
从 6500ms 到 49ms:一次 Java 内存布局优化的实录
java
摇滚侠9 小时前
IDEA 新建 Java 项目 学习 Java SE
java·学习·intellij-idea