欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring @Bean vs @Service注解区别

程序员文章站 2023-12-05 17:38:22
今天跟同事讨论了一下在spring boot中,是使用@configuration和@bean的组合来创建bean还是直接使用 @service等注解放在类上的方式。笔者倾...

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

先来看一个例子,目标是创建searchservice的一个bean。

直接使用@service的方式:

// searchservice.java
package li.koly.search;
import java.util.list;
public interface searchservice {
  list<object> search(string q);
}

// elasticsearchserviceimpl.java
package li.koly.search;
import org.springframework.stereotype.service;
import java.util.arrays;
import java.util.list;
@servicecomponent
public class elasticsearchserviceimpl implements searchservice {
  @override
  public list<object> search(string q) {
    return arrays.aslist("hello", q);
  }
}

// application.java
package 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
@restcontroller
public 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.java
package 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.java
package li.koly.search;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;

@configuration
public 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的方式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。