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 小时前
从输入 juejin.cn 到看到页面:DNS、Nginx、服务器集群与 CDN 到底在做什么?
后端·mysql
东风破_3 小时前
从 0 设计一个博客数据库:用户、头像与文章表应该怎么建?
后端·mysql
大鸡腿同学4 小时前
黄仁勋点透的 AI 真相:能实现你知道但做不到的,却实现不了你不知道的
后端
FfHUCisI4 小时前
Go 编译过程全景
开发语言·后端·golang
FfHUCisI4 小时前
Golang 语法分析与 AST:Parser 与 go/ast
开发语言·后端·golang
秋饼4 小时前
JDK 27 企业级 AI 服务落地实战:G1 默认、紧凑对象头、后量子 TLS 与 JFR 脱敏全解析
java·ai·技术分享·后端开发
卓怡学长5 小时前
w176基于SpringBoot的医院管理系统
java·spring boot·spring·maven·intellij-idea
lemon_sjdk5 小时前
ObjectProperty
java·开发语言·算法
hh9505 小时前
Agent Plan x DeepSeek Harness:Agent 供应链安全与第三方插件审计
java·开发语言·安全·agent plan·adg成都社区·adg社区
吴声子夜歌5 小时前
Java面试——HBase原理及应用
java·面试·hbase