@Bean 和 @Component的区别

本文详细探讨了SpringBoot中@Component与@Bean注解的用途、区别,以及如何在实际项目中合理运用,强调了@Bean的灵活性和第三方库集成的重要性。

前言  

最近研究Springboot 源码的时候发现这两个注解比较常出现,但是放眼看去这两个注解好像功能都差不多,所以专门研究了一下:

注解作用

  • @Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。同样的还有@Service、@Resiposity、@Controller。
  • @Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。通常方法体中包含了最终产生bean实例的逻辑。

两者对比

相同点:两者的结果都是为spring容器注册Bean.

不同点:@Component 通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中。

    @Bean 注解通常是我们在标有该注解的方法中定义产生这个bean的逻辑。

例如,我们在application中定义两个Bean,然后注入到我们需要的类中使用

@SpringBootApplication
public class ScheduleApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ScheduleApplication.class,args);
    }
    
    
    @Bean
    public ThreadPoolTaskExecutor mythreadpool(){
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //设置核心线程数
        taskExecutor.setCorePoolSize(5);
        //设置最大线程数
        taskExecutor.setMaxPoolSize(100);
        //设置线程空闲等待时间
        taskExecutor.setKeepAliveSeconds(60);
        //设置任务等待队列的大小
        taskExecutor.setQueueCapacity(60);
        // 设置线程池内线程名称的前缀-------阿里编码规约推荐--方便出错后进行调试
        taskExecutor.setThreadNamePrefix("mythreadpool-");
        //设置任务的拒绝策略
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        //初始化
        taskExecutor.initialize();
        return taskExecutor;
    }


    @Bean("visiableThreadPool")
    public ThreadPoolTaskExecutor visiableThreadPool(){
        ThreadPoolTaskExecutor visiableThreadPool = new VisiableThreadPool();
        visiableThreadPool.setCorePoolSize(10);
        visiableThreadPool.setMaxPoolSize(1000);
        visiableThreadPool.setKeepAliveSeconds(60);
        visiableThreadPool.setQueueCapacity(1000);
        visiableThreadPool.setThreadNamePrefix("visiableThreadPool-");
        visiableThreadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        visiableThreadPool.initialize();
        return visiableThreadPool;
    }
}
@Service
public class TaskServiceImpl implements TaskService {
    
    @Resource(name = "visiableThreadPool")
    private ThreadPoolTaskExecutor threadPool;
    
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    
...
    
    @Override
    @Transactional
    public long addTask(Task task) throws ScheduleSystemException {

        Future<Long> future = threadPool.submit(() -> {
        
        ...

    }


    @Override
    public void refresh(){

        threadPool.execute(() -> {
             
              ...

        });
    }
}

理解

@Component (@Controller @Service @Respository)作用于类上,只有在我们的SpringBoot应用程序启用了组件扫描并且包含了被注解的类时才有效。通过组件扫描,Spring将扫描整个类路径,并将所有@Component注释类添加到Spring Context,这里有的不足就是会把整个类当成bean注册到spring 容器上,如果这个类中并不是所有方法都需要注册为bean的话,会出现不需要的方法都注册成为bean,这时候必须确保这些不需要的方法也能注册为bean或者在扫描中加filter 过滤这些不需要的bean,否者spring将无法成功启动。

@Bean相对来说就更加灵活了,它可以独立加在方法上,按需注册到spring容器,而且如果你要用到第三方类库里面某个方法的时候,你就只能用@Bean把这个方法注册到spring容器,因为用@Component你需要配置组件扫描到这个第三方类路径而且还要在别人源代码加上这个注解,很明显是不现实的。

`@Bean` `@Component` 是 Spring 框架中用于创建管理 Bean 的注解,它们的区别主要体现在以下几个方面: ### 作用对象 - `@Component` 注解作用于类,通常是通过路径扫描来自动侦测以及自动装配到 Spring 容器中,可以使用 `@ComponentScan` 注解定义要扫描的路径,从中找出标识了需要装配的类自动装配到 SpringBean 容器中。 - `@Bean` 注解作用于方法,在标有该注解的方法中定义产生这个 Bean,告诉 Spring 这是某个类的实例,当需要用它的时候再获取 [^1]。 ### 控制权灵活性 - 使用 `@Component` 注解的类,其实例化装配过程由 Spring 完全控制,通常用于标识自动扫描的组件。 - 使用 `@Bean` 注解的方法,可以完全控制 Bean 的创建过程,可以在方法体内定义任何需要的逻辑来实例化对象,通常用于特殊配置需求或第三方类的实例化 [^2]。 ### 使用场景 - `@Component` 用于标记自己编写的类,如 `Service`、`Repository`、`Controller` 等,让 Spring 自动扫描并创建实例(Bean)。 - `@Bean` 用于注册第三方库的类或需要复杂初始化逻辑的类,当引用第三方库中的类需要装配到 Spring 容器时,只能通过 `@Bean` 来实现 [^1][^3]。 ### 代码示例 #### `@Component` 示例 ```java import org.springframework.stereotype.Component; @Component public class MyComponent { public void doSomething() { System.out.println("Doing something in MyComponent"); } } ``` #### `@Bean` 示例 ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public MyBean myBean() { return new MyBean(); } } class MyBean { public void doSomething() { System.out.println("Doing something in MyBean"); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值