概述:
Controller、Service、Repository这三个注解都是Spring提供的,他们三个有着相似的作用,即将被注解类的实例放入到Spring容器中,作用很相似那他们有什么区别呢?
一、根据三者的源码分析他们的区别
1.controller
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { @AliasFor( annotation = Component.class ) String value() default ""; }
2.Service
备注:这里讨论的Service是org.springframework.stereotype下的Service,不是dubbo的
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Service { @AliasFor( annotation = Component.class ) String value() default ""; }
3.Repositroy
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { @AliasFor( annotation = Component.class ) String value() default ""; }
4.Spring是如何创建被他们修饰类的实例,并将其放入到Spring容器中呢?
在SSM架构中我们需要配置包扫描,来将这些被Compomen、Controller、Service、Repositroy注解修饰的类的实例放入到Spring容器中,如今SpringBoot、SpringCloud中都是自动配置,只要我们在类上加了这些注解注解他们的实例就会被放入到Spring容器中。那他们的对象又是如何被创建出来的呢?其实Spring底层使用的是工厂+反射的技术创建的这些对象,且这些对象默认都是单例。在SpringBoot中会先拿到这些注解所在类的全限定名,然后通过全限定名进行反射创建他们的对象,然后放入到Spring容器中。
5.作用上的区别
首先我们可以看到他们三个的源码接口中使用的注解都是一样的,如下:
@Target({ElementType.TYPE}):表示当前的注解类可以在类、接口、枚举类型上使用
@Retention(RetentionPolicy.RUNTIME):表示被注解类(这里是Controller、Service等等所修饰的类)上的Controller、Service会被保留到JVM运行该类期间
@Documented:表示使用javadoc生成api文档时会保留注解类的的内容,无关紧要
@Component:这是Spring提供的组件注入注解,也是这里讨论的内容
观察了源码中上面这四个注解,我们发现唯一对功能有影响的地方其实就是Component注解了,其他注解都是使用上的与具体功能无关。那么我们再往下看会发现,他们三个接口中的主体内容都是一样的,如下:
@AliasFor( annotation = Component.class ) String value() default "";
AliasFor注解的作用是起别名,这里使用这个注解的作用就是将默认方法与Component中的默认方法进行值传递了,在我们不指定值时他们都是“”,若是为Controller、Service、Repository他们指定值,则也就是为Component指定了。
综合以上两点,就很明显了,当Controller、Service、Repository的所有处理其实都是相当于交给了Component处理,其实这三个注解是与Component没有什么区别的,无论实现还是使用上,都是如此,Spring只不过是为了区别控制层、业务层、数据层而产生的三个衍生注解而已,真实情况使用他们三个是没有区别的。
6.验证他们使用是否有区别
我们通过看他们的实现得出结论他们没有区别,那是不是真没有区别,再来验证下,笔者分别在控制层上使用Controller、Service、Repository、Component最后请求都正常进入到了接口中,当然还有很多其他场景需要验证,但是都大同小异,这里就不做过多验证了。若是你有不同观点,欢迎指点,下面展示下其中一种的验证结果: