前言
最近研究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你需要配置组件扫描到这个第三方类路径而且还要在别人源代码加上这个注解,很明显是不现实的。