Spring @Bean vs @Service注解区别

今天跟同事讨论了一下在Spring Boot中,是使用@Configuration和@Bean的组合来创建Bean还是直接使用 @Service等注解放在类上的方式。笔者倾向于使用第一种,即@Configuration和@Bean的组合。

先来看一个例子,目标是创建SearchService的一个Bean。

直接使用@Service的方式:
 

  1. // SearchService.java
  2. package li.koly.search;
  3.  
  4. import java.util.List;
  5.  
  6. public interface SearchService {
  7.     List<Object> search(String q);
  8. }
  9.  
  10. // ElasticSearchServiceImpl.java
  11. package li.koly.search;
  12.  
  13. import org.springframework.stereotype.Service;
  14. import java.util.Arrays;
  15. import java.util.List;
  16.  
  17. @ServiceComponent
  18. public class ElasticSearchServiceImpl implements SearchService {
  19.     @Override
  20.     public List<Object> search(String q) {
  21.         return Arrays.asList("hello", q);
  22.     }
  23. }
  24.  
  25. // Application.java
  26. package li.koly.search;
  27.  
  28. import org.springframework.beans.factory.annotation.Autowired;
  29. import org.springframework.boot.SpringApplication;
  30. import org.springframework.boot.autoconfigure.SpringBootApplication;
  31. import org.springframework.web.bind.annotation.GetMapping;
  32. import org.springframework.web.bind.annotation.RestController;
  33. import java.util.List;
  34.  
  35. @SpringBootApplication
  36. @RestController
  37. public class Application {
  38.     @Autowired
  39.     private SearchService searchService;
  40.  
  41.     @GetMapping("/search")
  42.     public List<Object> hello(String q) {
  43.         return searchService.search(q);
  44.     }
  45.  
  46.     public static void main(String[] args) {
  47.         SpringApplication.run(Application.class, args);
  48.     }
  49.  
  50. }

复制代码




启动Application,浏览器访问: http://localhost:8081/search?q=koly ,页面显示:["hello","koly"]

使用@Configuration和@Bean的方式:

 

  1. // ElasticSearchServiceImpl.java
  2. package li.koly.search;
  3.  
  4. import java.util.Arrays;
  5. import java.util.List;
  6.  
  7. public class ElasticSearchServiceImpl implements SearchService {
  8.    @Override
  9.    public List<Object> search(String q) {
  10.        return Arrays.asList("hello", q);
  11.    }
  12. }
  13.  
  14. // AppConfig.java
  15. package li.koly.search;
  16.  
  17. import org.springframework.context.annotation.Bean;
  18. import org.springframework.context.annotation.Configuration;
  19.  
  20. @Configuration
  21. public class AppConfig {
  22.    @Bean
  23.    public SearchService searchService() {
  24.        return new ElasticSearchServiceImpl();
  25.    }
  26. }

复制代码





相比直接使用@Service的代码,多了一个AppConfig类,移除了放在ElasticSearchServiceImpl上面的@Service注解。一眼看去,代码和类还多了。那么使用后者的好处是什么呢?

笔者认为,好处有:

关注点分离

使用@Configuration和@Bean的方式,Bean的创建全部放到了一个地方,接口及其实现完全跟Bean创建没有了关系。

如果Bean的创建需要改动,那么只需要查看并修改对应的Configuration类就行,并不需要去到对应的Java Bean进行改动。比如可能有时候Bean创建需要同@Scope或者@Profile配合,此时只需要修改Configuration类就行了。

单一职责

@service注解本身就承担了两个职责:

一是Bean的创建;
二是将一个类标识为一个服务。
Indicates that an annotated class is a "Service", originally defined by Domain-Driven

Design (Evans, 2003) as "an operation offered as an interface that stands alone in the model, with no encapsulated state."

上面是Spring对于@Service注解的说明。也就是说@Service实际上表示了DDD中的无状态的,独立的,以接口的形式提供的一个操作。

而采用@Bean和@Configuration配合的方式,Bean的创建交给了单独的类,而Service的标识交给了Java中的Interface以及类的名字。这点在Spring Data也有所体现,比如Repository就是通过名字来标识,如CrudRepository。因此Service也通过名字来体现。具体层次定义,通过名字而不依赖Spring提供的注解,便于根据项目提供更多的层次,比如Mapper层,Validator层等。

另为,本身Bean和Service就是两个维度的概念。一个关于具体实现,另一个关于DDD中的概念。

更灵活

使用@Bean的方式,能够创建库里面的类的实例。如果使用@Service的方式,没办法在库里面对应的类上添加@Service注解。

least knowledge(最小知识原则)

最小知识原则的意思是:

完成功能需要的技术或者知识越少越好,这样才能保证项目简单,同时降低项目的学习难度。

由于使用@Service无法创建类库中的类的实例,因此在遇到类似需求时,不得不使用@Configuration和@Bean的形式。此时,整个项目中就同时存在@Service,@Configuration和@Bean等注解,而这些注解所做的事情都是一样的,即Bean的创建。

使用@Service,很有可能出现@Service,@Component,@Configuration和@Bean同时存在的情况。

而使用@Configuration和@Bean则完全可以不使用@Service和@Component,符合最小知识原则。

最后,顺便说一句,之前Spring的Bean创建是在xml里面,后面使用了Java做配置。不使用xml的主要原因是xml不够简洁,且没有编译时检查等功能,而不是说需要将Bean的创建分散到各个类里。

综上,笔者更倾向与使用@Configuration和@Bean的方式。

转自https://www.jb51.net/article/130443.htm

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值