经常使用Spring的注解@Controller @Service @Repository @Component,却不知道他们之间有什么区别,一起来看看。
一、源码
- @Component
public @interface Component {
String value() default "";
}
- @Repository
@Component
public @interface Repository {
@AliasFor(annotation = Component.class)
String value() default "";
}
- @Service
@Component
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}
- @Controller
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}
以上代码省略了一些细节,看了以上代码你就会发现无论是@Controller
、@Service
还是@Repository
全部都被@Component
注解了。在Spring源码中,注解会一级一级向上递归搜索,搜索所有的注解信息,即被以上注解注解的类在Spring看来都会包含@Component注解。 而@Component
在原文表述为:
/**
* Indicates that an annotated class is a "component".
* Such classes are considered as candidates for auto-detection
* when using annotation-based configuration and classpath scanning.
* 表明被注释的类是一个“组件”。
* 当使用基于注释的配置或类路径扫描时,这些类被视为自动检测的候选类。
*
* <p>Other class-level annotations may be considered as identifying
* a component as well, typically a special kind of component:
* e.g. the {@link Repository @Repository} annotation or AspectJ's
* {@link org.aspectj.lang.annotation.Aspect @Aspect} annotation.
*
* @author Mark Fisher
* @since 2.5
* @see Repository
* @see Service
* @see Controller
* @see org.springframework.context.annotation.ClassPathBeanDefinitionScanner
*/
综上所述,本质上@Controller
、@Service
、@Repository
、@Component
本质都是@Component
,即Spring容器中的一个组件。
二、如果都相同,那为什么不直接都用@Component
就好了?
相信做过java web的都知道MVC的概念,都知道一个基于MVC的java web项目一般可以简单划分为:Controller、Service、Dao、Util等,如果给Controller、Service、Dao都使用@Component
那么不利于逻辑分层,添加这三个注解的主要目的就是为了逻辑分层,无论开发者给Controller命名为XxxYyyZzz还是AaaBbbCcc,只要注解有@Controller,那么可以理解为祖传代码的意思就是这一块就是Controller层。
三、这几个注解真的没区别吗?
如下代码:
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Component
public class DiffController {
@RequestMapping("hello")
@ResponseBody
public Object hello(){
return "hello world!";
}
}
在网页中访问会404。
而当我使用@Controller
进行注解时便会出现如下结果:
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class DiffController {
@RequestMapping("hello")
@ResponseBody
public Object hello(){
return "hello world!";
}
}
而当我使用如下代码时发现也能正常访问网页:
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Component
@RequestMapping("")
public class DiffController {
@RequestMapping("hello")
@ResponseBody
public Object hello(){
return "hello world!";
}
}
所以在Spring Boot 中只有被@Controller
和@RequestMapping
注解时Spring才会去扫描内部的@RequestMapping
,具体是在哪个版本加入的就后面有时间看看。
附录:环境
Spring Boot 2.4.0
Windows 10 1909 企业版