时间:2021-05-20
今天跟同事讨论了一下在Spring Boot中,是使用@Configuration和@Bean的组合来创建Bean还是直接使用 @Service等注解放在类上的方式。笔者倾向于使用第一种,即@Configuration和@Bean的组合。
先来看一个例子,目标是创建SearchService的一个Bean。
直接使用@Service的方式:
// SearchService.javapackage li.koly.search;import java.util.List;public interface SearchService { List<Object> search(String q);}// ElasticSearchServiceImpl.javapackage li.koly.search;import org.springframework.stereotype.Service;import java.util.Arrays;import java.util.List;@ServiceComponentpublic class ElasticSearchServiceImpl implements SearchService { @Override public List<Object> search(String q) { return Arrays.asList("hello", q); }}// Application.javapackage li.koly.search;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;@SpringBootApplication@RestControllerpublic class Application { @Autowired private SearchService searchService; @GetMapping("/search") public List<Object> hello(String q) { return searchService.search(q); } public static void main(String[] args) { SpringApplication.run(Application.class, args); }}启动Application,浏览器访问: http://localhost:8081/search?q=koly ,页面显示:["hello","koly"]
使用@Configuration和@Bean的方式:
// ElasticSearchServiceImpl.javapackage li.koly.search;import java.util.Arrays;import java.util.List;public class ElasticSearchServiceImpl implements SearchService { @Override public List<Object> search(String q) { return Arrays.asList("hello", q); }}// AppConfig.javapackage li.koly.search;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class AppConfig { @Bean public SearchService searchService() { return new ElasticSearchServiceImpl(); }}相比直接使用@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的方式。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
声明bean的注解:@Component组件,没有明确角色的bean@Service,在业务逻辑层(service)中使用@Repository,在数据访问层(
Spring@Configuration和@Component区别一句话概括就是@Configuration中所有带@Bean注解的方法都会被动态代理,因此调用
我们不妨先将spring常用的注解按照功能进行分类1、将普通类加入容器形成Bean的注解日常开发中主要使用到的定义Bean的注解包括(XML方式配置bean暂不
Spring@Configuration注解Spring3.0开始,@Configuration用于定义配置类,定义的配置类可以替换xml文件,一般和@Bean
使用注解来构造IoC容器用注解来向Spring容器注册Bean。需要在applicationContext.xml中注册。如:在base-package指明一个