component-scan>
上面的配置将隐式地向Spring容器注册、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor以及这4个专门用于处理注解的Bean后置处理器。
下面将具体介绍这4个注解后置处理器。
:
是Spring容器专门处理配置了自动依赖注入装配相关注解(@Autowire、@Value以及其他JSR-330注解)的Bean后置处理器,其主要功能源码如下:
(1).的构造方法:
AutowiredAnnotationBeanPostProcessor只有一个的构造方法,其源码如下:
[java]viewplaincopy
3publicAutowiredAnnotationBeanPostProcessor(){
4//后置处理器将处理@Autowire注解
5this.autowiredAnnotationTypes.add(Autowired.class);
6//后置处理器将处理@Value注解
7this.autowiredAnnotationTypes.add(Value.class);
8//获取当前类的类加载器
9ClassLoadercl=AutowiredAnnotationBeanPostProcessor.class.getClassLoader();
10try{
11//后置处理器将处理javax.inject.InjectJSR-330注解
12this.autowiredAnnotationTypes.add((Class
extendsAnnotation>)cl.loadClass("javax.inject.Inject"));
13logger.info("JSR-330'javax.inject.Inject'annotationfoundandsupportedforautowiring");
14}
15catch(ClassNotFoundExceptionex){
16//JSR-330APInotavailable-simplyskip.
17}
18}
(2).为指定类选择其合适的构造方法:
容器对指定类进行自动依赖注入装配(autowiring)时,容器需要对Bean调用合适的构造方法创建实例对象,AutowiredAnnotationBeanPostProcessor为指定类选择相应的构造方法,源码如下:
[java]viewplaincopy
19//为自动依赖注入装配Bean选择合适的构造方法
20publicConstructor[]determineCandidateConstructors(ClassbeanClass,StringbeanName)throwsBeansException{
21//首先从容器的缓存中查找是否有指定Bean的构造方法
22Constructor[]candidateConstructors=this.candidateConstructorsCache.get(beanClass);
23//容器缓存中没有给定类的构造方法
24if(candidateConstructors==null){
25//线程同步以确保容器中数据一致性
26synchronized(this.candidateConstructorsCache){
27candidateConstructors=this.candidateConstructorsCache.get(beanClass);
28if(candidateConstructors==null){
29//通过JDK反射机制,获取指定类的中所有声明的构造方法
30Constructor[]rawCandidates=beanClass.getDeclaredConstructors();
31//存放候选构造方法的集合
32Listcandidates=newArrayList(rawCandidates.length);
33//autowire注解中required属性指定的构造方法
34ConstructorrequiredConstructor=null;
35//默认的构造方法
36ConstructordefaultConstructor=null;
37//遍历所有的构造方法,检查是否添加了autowire注解,以及是否
38//指定了required属性
39for(Constructor
>candidate:
rawCandidates){
40//获取指定类中所有关于autowire的注解(Annotation)
41Annotationannotation=findAutowiredAnnotation(candidate);
42//如果指定类中有关于antowire的注解
43if(annotation!
=null){
44//如果antowire注解中指定了required属性
45if(requiredConstructor!
=null){
46thrownewBeanCreationException("Invalidautowire-markedconstructor:
"+candidate+
47".Foundanotherconstructorwith'required'Autowiredannotation:
"+
48requiredConstructor);
49}
50//如果autowire注解的参数列表为空
51if(candidate.getParameterTypes().length==0){
52thrownewIllegalStateException(
53"Autowiredannotationrequiresatleastoneargument:
"+candidate);
54}
55//获取autowire注解中required属性值
56booleanrequired=determineRequiredStatus(annotation);
57//如果获取到autowire注解中required的属性值
58if(required){
59//如果候选构造方法集合不为空
60if(!
candidates.isEmpty()){
61thrownewBeanCreationException(
62"Invalidautowire-markedconstructors:
"+candidates+
63".Foundanotherconstructorwith'required'Autowiredannotation:
"+
64requiredConstructor);
65}
66//当前的构造方法就是required属性所配置的构造方法
67requiredConstructor=candidate;
68}
69//将当前的构造方法添加到哦啊候选构造方法集合中
70candidates.add(candidate);
71}
72//如果类中没有autowire的相关注解,并且构造方法参数列表为空
73elseif(candidate.getParameterTypes().length==0){
74//当前的构造方法是默认构造方法
75defaultConstructor=candidate;
76}
77}
78//如果候选构造方法集合不为空
79if(!
candidates.isEmpty()){
80//如果所有的构造方法都没有配置required属性,且有默认构造方法
81if(requiredConstructor==null&&defaultConstructor!
=null){
82//将默认构造方法添加到候选构造方法列表
83candidates.add(defaultConstructor);
84}
85//将候选构造方法集合转换为数组
86candidateConstructors=candidates.toArray(newConstructor[candidates.size()]);
87}
88//如果候选构造方法集合为空,则创建一个空的数组
89else{
90candidateConstructors=newConstructor[0];
91}
92//将类的候选构造方法集合存放到容器的缓存中
93this.candidateConstructorsCache.put(beanClass,candidateConstructors);
94}
95}
96}
97//返回指定类的候选构造方法数组,如果没有返回null
98return(candidateConstructors.length>0?
candidateConstructors:
null);
99}
(3).AutowiredAnnotationBeanPostProcessor对方法和属性的依赖注入:
当Spring容器对配置了autowire相关注解的Bean进行依赖注入时,后置处理器对属性和对象进行自动注入处理,源码如下:
[java]viewplaincopy
100//处理类中的属性
101publicPropertyValuespostProcessPropertyValues(
102PropertyValuespvs,PropertyDescriptor[]pds,Objectbean,StringbeanName)throwsBeansException{
103//获取指定类中autowire相关注解的元信息
104InjectionMetadatametadata=findAutowiringMetadata(bean.getClass());
105try{
106//对Bean的属性进行自动注入
107metadata.inject(bean,beanName,pvs);
108}
109catch(Throwableex){
110thrownewBeanCreationException(beanName,"Injectionofautowireddependenciesfailed",ex);
111}
112returnpvs;
113}
114//处理对象的注入
115publicvoidprocessInjection(Objectbean)throwsBeansException{
116//获取给定Bean的Class对象
117Class
>clazz=bean.getClass();
118//获取给定类中autowire相关注解元信息
119InjectionMetadatametadata=findAutowiringMetadata(clazz);
120try{
121//对Bean对象进行自动注入
122metadata.inject(bean,null,null);
123}
124catch(Throwableex){
125thrownewBeanCreationException("Injectionofautowireddependenciesfailedforclass["+clazz+"]",ex);
126}
127}
128//获取给定类的autowire相关注解元信息
129privateInjectionMetadatafindAutowiringMetadata(Classclazz){
130//首先从容器中查找是否有给定类的autowire相关注解元信息
131InjectionMetadatametadata=this.injectionMetadataCache.get(clazz);
132if(metadata==null){
133synchronized(this.injectionMetadataCache){
134metadata=this.injectionMetadataCache.get(clazz);
135if(metadata==null){
136//解析给定类autowire相关注解元信息
137metadata=buildAutowiringMetadata(clazz);
138//将得到的给定类autowire相关注解元信息存储在容器缓存中
139this.injectionMetadataCache.put(clazz,metadata);
140}
141}
142}
143returnmetadata;
144}
145//解析给定类autowire相关注解元信息
146privateInjectionMetadatabuildAutowiringMetadata(Classclazz){
147//创建一个存放注解元信息的集合
148LinkedListelements=newLinkedList();
149Class
>targetClass=clazz;
150//递归遍历当前类及其所有基类,解析全部注解元信息
151do{
152//创建一个存储当前正在处理类注解元信息的集合
153LinkedListcurrElements=newLinkedList();
154//利用JDK反射机制获取给定类中所有的声明字段,获取字段上的注解信息
155for(Fieldfield:
targetClass.getDeclaredFields()){
156//获取给定字段上的注解
157Annotationannotation=findAutowiredAnnotation(field);
158if(annotation!
=null){
159//如果给定字段是静态的(Static),则直接遍历下一个字段if(Modifier.isStatic(field.getModifiers())){
160if(logger.isWarnEnabled()){
161logger.warn("Autowiredannotationisnotsupportedonstaticfields:
"+field);
162}
163continue;
164}
165//判断注解的required属性值是否有效
166booleanrequired=determineRequiredStatus(annotation);
167//将当前字段元信息封装,添加在返回的集合中
168currElements.add(newAutowiredFieldElement(field,required));
169}
170}
171//利用JDK反射机制获取给定类中所有的声明方法,获取方法上的注解信息
172for(Methodmethod:
targetClass.getDeclaredMethods()){
173//获取给定方法上的所有注解
174Annotationannotation=findAutowiredAnnotation(method);
175if(annotation!
=null&&method.equals(ClassUtils.getMostSpecificMethod(method,clazz))){
176//如果方法是静态的,则直接遍历下一个方法
177if(Modifier.isStatic(method.getModifiers())){
178if(logger.isWarnEnabled()){
179logger.warn("Autowiredannotationisnotsupportedonstaticmethods:
"+method);
180}
181continue;
182}
183//如果方法的参数列表为空
184if(method.getParameterTypes().length==0){
185if(logger.isWarnEnabled()){
186logger.warn("Autowiredannotationshouldbeusedonmethodswithactualparameters:
"+method);
187}
188}
189//判断注解的required属性值是否有效
190booleanrequired=determineRequiredStatus(annotation);
191//获取当前方法的属性描述符,即方法是可读的(readable)getter方法,
192//还是可写的(writeable)setter方法
193PropertyDescriptorpd=BeanUtils.findPropertyForMethod(method);
194//将方法元信息封装添加到返回的元信息集合中
195currElements.add(newAutowiredMethodElement(method,required,pd));
196}
197}
198//将当前类的注解元信息存放到注解元信息集合中
199elements.addAll(0,currElements);
200//获取给定类的父类
201targetClass=targetClass.getSuperclass();
202}
203//如果给定类有基类,并且基类不是Object,则递归获取其基类的元信息
204while(targetClass!
=null&&targetClass!
=Object.class);
205returnnewInjectionMetadata(clazz,elements);
206}
207//获取给定对象的autowire相关注解
208privateAnnotationfindAutowiredAnnotation(AccessibleObjectao){
209//遍历所有autowire相关的注解:
@Autowire、@Value以及JSR-330等
210for(Class
extendsAnnotation>type:
this.autowiredAnnotationTypes){
211//获取给定对象上的指定类型的注解
212Annotationannotation=ao.getAnnotation(type);
213if(annotation!
=null){
214returnannotation;
215}
216}
217returnnull;
218}
(4).AutowiredAnnotationBeanPostProcessor对字段和方法的注入:
a.AutowiredAnnotationBeanPostProcessor对字段的注入是通过AutowiredFieldElement类的inject方法实现的,源码如下:
[java]viewplaincopy
219//对字段进行注入
220protectedvoidinject(Objectbean,StringbeanName,PropertyValuespvs)throwsThrowable{
221//获取注入元素对象
222Fieldfield=(Field)this.member;
223try{
224Objectvalue;
225//如果当前对象在容器中被缓存
226if(this.cached){
227//根据Bean名称解析缓存中的字段值
228value=resolvedCachedArgument(beanName,this.cached