在 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. 实现 InitializingBean 或 BeanPostProcessor
在 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。