References
有关 Annotation-based 相关的注解说明参考官方文档【7.10.1】@Component and further stereotype annotations;
将相关重要的部分摘录如下,
@Repository
,@Service
, and@Controller
是@Component
的特殊例子,分别用在 persistence, service, and presentation layers;现在,你也可以使用@Component
来统一注解,
Spring 目前没有特别区分上述的几种注解方式,不过按照约定,最好在持久化层使用@Repository
,在服务层使用@Service
,在 web 控制层使用@Controller
,你也可以统一使用@Component
;
前言
虽然标题为讲解@Service
,实际上会牵涉到@Component
、@Repository
, @Controller
等概念;
本文为作者的原创作品,转载需注明出处;
源码分析环境搭建
参考 Spring Core Container 源码分析一:环境准备
源码分析
meta annotation
Spring 目前没有特别区分 @Repository
, @Service
和 @Controller
这几种注解方式,你也可以统一使用@Component
注解;那为什么呢?其实答案就是@Repository
, @Service
和@Controller
这三类注解都是通过@Component
注解生成的,类似于 Annotation 中的继承机制;看看 Service 注解的源码就清楚了,
1 | (ElementType.TYPE) |
可见,@Service
本身也就是一个@Component
;有关 meta annotation 的详细描述参看【7.10.2】Meta-annotations;
测试用例
这里继续沿用 Spring Beans 初始化流程分析中所使用到的测试用例;这里呢,我们为 Person 对象添加一个服务对象 DogService,该服务对象提供遛狗服务;
DogService.java
1 | package org.shangyang.spring.container; |
将其声明为 @Service,表示 DogService 是一个容器服务对象实例;
Person.java
1 | package org.shangyang.spring.container; |
将容器中的 DogService 实例通过 @Autowired 注入当前对象 Person;
beans.xml
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
这里使用 <context:component-scan> 扫描并注入由 @Service 注解的 bean 到容器中;
_测试_
1 |
|
输出结果,
1 | walks the dog Niba |
Ok,john 调用遛狗服务成功;下面,我们来看看 Spring 底层容器是如何实现的?
流程分析
当分析完章节 Spring Core Container 源码分析七:注册 Bean Definitions,这部分其实就简单许多了;
通过解析 <context:component-scan base-package=”org.shangyang” /> 元素,触发 ContextNamespaceHandler 的 do scan 流程的操作,该过程就是去遍历由 base-package 所指定路径下的所有 .class 文件,找到并解析与 @Component、@Service、@Repository 等相关的 .class,并生成相应的 annotation-bean-definitions,将其注册到当前的 bean factory 中;具体过程参考 do scan 流程,不再赘述;
通过 @Autowired 注解注入由 @Component、@Service 等注解所生成的 bean 实例对象,该步骤参考 AutowiredAnnotationBeanPostProcessor部分,这里不再赘述;
通过上述两个步骤,完成了通过 @Autowired 注入 @Component 实例到当前 bean 的过程;