抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

SpringIOC-公共注解的支持

CommonAnnotationBeanPostProcessor类

CommonAnnotationBeanPostProcessor继承了InitDestroyAnnotationBeanPostProcessor,这两个注解是由这个父类完成解析的,在CommonAnnotationBeanPostProcessor构造函数中调用父类的方法setInitAnnotationType()和setDestroyAnnotationType()将这两个注解Class对象传递给父类。

对@PostConstruct和@PreDestroy注解的处理以及@Resources处理

构造方法

主要完成对@PostConstruct以及@PreDestroy扫描的设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Create a new CommonAnnotationBeanPostProcessor,
* with the init and destroy annotation types set to
* {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy},
* respectively.
* CommonAnnotationBeanPostProcessor的构造方法
* 设置了initAnnotationType 以及 destroyAnnotationType
*/
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}

搜集注解

搜集@PostConstruct,@PreDestroy和@Resources的注解

postProcessMergedBeanDefinition

扫描类里面的属性或者方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 1、扫描类里面的属性或者方法
* 2、判断属性或者方法上面是否有@PostConstruct @PreDestroy @Resource注解
* 3、如果有注解的属性或者方法,包装成一个类
*/
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//1. 扫描@PostConstruct @PreDestroy
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
//2. 扫描@Resource,扫描属性和方法上面是否有@Resource注解,如果有则收集起来封装成对象
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
//3. 检测ConfigMembers并将InjectedElement集合赋值给全局的checkedElements
metadata.checkConfigMembers(beanDefinition);
}

​ 在实例化一个bean后此时还未进行依赖注入时,每个bean definition会被MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()方法执行一遍用来获取一些元数据来增加额外的功能,InitDestroyAnnotationBeanPostProcessor就是将bean定义了被@PostConstruct和@PreDestroy注解的方法缓存到一个Map中,供之后BeanPostProcessor.postProcessBeforeInitialization()和DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()阶段可以直接获取这些方法来执行。

postProcessMergedBeanDefinition

调用父类的postProcessMergedBeanDefinition

父类是InitDestroyAnnotationBeanPostProcessor

扫描方法的initMethod和destroyMethod并将对应的注解封装成LifecycleMetadata

1
2
3
4
5
6
7
8
9
10
11
/**
* 扫描方法的initMethod和destroyMethod并将对应的注解封装成LifecycleMetadata
*
*/
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//1. 根据class获取LifecycleMetadata封装了 initMethod和destroyMethod的列表
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
//2. 检测BeanDefinition和LifecycleElement的对应关系并给全局的checkedInitMethods,checkedDestroyMethods赋值
metadata.checkConfigMembers(beanDefinition);
}
findLifecycleMetadata

根据class 获取获取initMethod和destroyMethod并封装成LifecycleMetadata

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 根据class 获取获取initMethod和destroyMethod
* 并封装成LifecycleMetadata
*/
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
//1. 如果缓存对象为空
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
//2. 获取initMethod和destroyMethod并封装成LifecycleMetadata
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
//3. 从缓存中获取LifecycleMetadata
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
//3.1 从缓存中获取LifecycleMetadata 防止并发情况
metadata = this.lifecycleMetadataCache.get(clazz);
//3.2 如果缓存中没有
if (metadata == null) {
//3.3 获取initMethod和destroyMethod并封装成LifecycleMetadata
metadata = buildLifecycleMetadata(clazz);
//3.4 加入缓存
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}

​ findLifecycleMetadata方法内部主要调用buildLifecycleMetadata方法完成生命周期方法的,其余部分是缓存的操作不关心。

buildLifecycleMetadata

获取initMethod和destroyMethod 并封装成LifecycleMetadata

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* 获取initMethod和destroyMethod
* 并封装成LifecycleMetadata
*/
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
//1. 如果注解没有initMethod,destroyMethod注解则返回空的list
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
//initMethod列表
List<LifecycleElement> initMethods = new ArrayList<>();
//destroyMethod 列表
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;

do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
//2. 对所有class的method进行回调
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//2.1 如果initAnnotationType不为空并且method中有initAnnotationType这个注解类型就创建LifecycleElement并加入到currInitMethods
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
//2.2 创建LifecycleElement
LifecycleElement element = new LifecycleElement(method);
//2.3 加入到currInitMethods
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
//2.4 如果destroyAnnotationType不为空并且method中有destroyAnnotationType这个注解类型就创建LifecycleElement并加入到currDestroyMethods
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
//2.5 创建LifecycleElement并加入到currDestroyMethods
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
//3. currInitMethods添加到initMethods
initMethods.addAll(0, currInitMethods);
//4. currDestroyMethods添加到destroyMethods
destroyMethods.addAll(currDestroyMethods);
//5. 将targetClass的父类赋值给targetClass
targetClass = targetClass.getSuperclass();
}
//6. 如果父类不是object 继续循环
while (targetClass != null && targetClass != Object.class);
//7. 将initMethods和destroyMethods封装成LifecycleMetadata返回
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
ReflectionUtils.doWithLocalMethods

所有的method进行回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Perform the given callback operation on all matching methods of the given
* class, as locally declared or equivalent thereof (such as default methods
* on Java 8 based interfaces that the given class implements).
* 对所有的method进行回调
*/
public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
//1 获取class的方法以及所有接口的方法
Method[] methods = getDeclaredMethods(clazz, false);
//2. 遍历所有的方法
for (Method method : methods) {
try {
//3. 对方法进行回调
mc.doWith(method);
} catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
}
getDeclaredMethods

获取clazz以及接口的所有方法的数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* 获取clazz以及接口的所有方法的数组
*
* @param clazz
* @param defensive
* @return
*/
private static Method[] getDeclaredMethods(Class<?> clazz, boolean defensive) {
Assert.notNull(clazz, "Class must not be null");
//1. 从缓存中获取方法的数组
Method[] result = declaredMethodsCache.get(clazz);
//如果缓存中不存在
if (result == null) {
try {
//2. 获取clazz的所有的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
//3. 获取clazz所有接口的所有方法
List<Method> defaultMethods = findConcreteMethodsOnInterfaces(clazz);
//4. 进行接口方法和本地方法的合并
if (defaultMethods != null) {
result = new Method[declaredMethods.length + defaultMethods.size()];
System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length);
int index = declaredMethods.length;
for (Method defaultMethod : defaultMethods) {
result[index] = defaultMethod;
index++;
}
} else {
result = declaredMethods;
}
//5. 将所有方法加入缓存
declaredMethodsCache.put(clazz, (result.length == 0 ? EMPTY_METHOD_ARRAY : result));
} catch (Throwable ex) {
throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() +
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
}
}
return (result.length == 0 || !defensive) ? result : result.clone();
}
LifecycleElement

LifecycleElement是一个内部类,保存了生命周期方法和方法的一个标识符,和一个invoke()方法用来调用被注解的方法。值得注意的是这个方法的可以是private的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* Class representing injection information about an annotated method.
*/
private static class LifecycleElement {
//方法
private final Method method;
//标识符
private final String identifier;

//构造方法,传入Method并生成identifier
public LifecycleElement(Method method) {
if (method.getParameterCount() != 0) {
throw new IllegalStateException("Lifecycle method annotation requires a no-arg method: " + method);
}
this.method = method;
this.identifier = (Modifier.isPrivate(method.getModifiers()) ?
ClassUtils.getQualifiedMethodName(method) : method.getName());
}

public Method getMethod() {
return this.method;
}

public String getIdentifier() {
return this.identifier;
}

//通过反射完成方法的调用
public void invoke(Object target) throws Throwable {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(target, (Object[]) null);
}

@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (!(other instanceof LifecycleElement)) {
return false;
}
LifecycleElement otherElement = (LifecycleElement) other;
return (this.identifier.equals(otherElement.identifier));
}

@Override
public int hashCode() {
return this.identifier.hashCode();
}
}
checkConfigMembers

检测BeanDefinition和LifecycleElement的对应关系并给全局的checkedInitMethods,checkedDestroyMethods赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* 检测BeanDefinition和LifecycleElement的对应关系并给全局的checkedInitMethods,checkedDestroyMethods赋值
*
* @param beanDefinition
*/
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set<LifecycleElement> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
//1. initMethod方法的检查以及设置
// 1.1 遍历检查所有的收集的initMethod方法
for (LifecycleElement element : this.initMethods) {
String methodIdentifier = element.getIdentifier();
// 1.2如果beanDefinition的externallyManagedConfigMembers属性不包含该methodIdentifier
if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
// 1.3将该methodIdentifier添加到beanDefinition的externallyManagedConfigMembers属性
beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
// 1.4并将element添加到checkedElements
checkedInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
Set<LifecycleElement> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
//2. destroyMethod方法的检查以及设置
//2.1 遍历检查所有的收集的destroyMethod方法
for (LifecycleElement element : this.destroyMethods) {
String methodIdentifier = element.getIdentifier();
// 2.2如果beanDefinition的externallyManagedConfigMembers属性不包含该methodIdentifier
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
// 2.3将该methodIdentifier添加到beanDefinition的externallyManagedConfigMembers属性
beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
// 2.4并将element添加到checkedElements
checkedDestroyMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
this.checkedInitMethods = checkedInitMethods;
this.checkedDestroyMethods = checkedDestroyMethods;
}

小结

到这里位置已经对@PostConstruct和@PreDestroy注解进行了收集工作,将会在会面进行调用

findResourceMetadata

根据@Resources注解查找实现了@Resources接口的属性和方法并封装成InjectionMetadata

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* 根据@Resources注解查找实现了@Resources接口的属性和方法并封装成InjectionMetadata
*
*/
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
//1. 返回类名作为缓存键,以便与自定义调用方向后兼容。
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
//2. 从缓存中获取
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
//2.1检查是否需要刷新 如果metadata为null或者class 不匹配就刷新
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
//2.2 再次获取缓存数据
metadata = this.injectionMetadataCache.get(cacheKey);
//2.3 再次检测刷新 防止多线程问题
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
//2.3.1 如果需要刷新
if (metadata != null) {
//2.3.2 清除数据
metadata.clear(pvs);
}
//主要看这个方法
//2.4 获取属性和方法的@Resources注解并封装成InjectionMetadata
metadata = buildResourceMetadata(clazz);
//2.5 加入缓存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
buildResourceMetadata

获取属性和方法的@Resources注解并封装成InjectionMetadata

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* 获取属性和方法的@Resources注解并封装成InjectionMetadata
*
*/
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
//1. 检查clazz中是否在@Resources注解,如果没有直接返回
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}

List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;

do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//2. 获取class所有的字段信息并进行回调
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//如果是javax.xml.ws.WebServiceRef的类的处理 不需要关注
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
//如果是javax.ejb.EJB的类的处理 不需要关注
} else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
//3. 检查字段是否有Resource注解出现
//重点关注
} else if (field.isAnnotationPresent(Resource.class)) {
//3.1 如果Resource对应的字段是静态的直接报错
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
//3.2 如果ignoredResourceTypes中没有对应字段的类型
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
//3.3 将对应的field包装成ResourceElement并加入到currElements
currElements.add(new ResourceElement(field, field, null));
}
}
});
//4. 获取class所有的方法信息并进行回调
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//5. 找出我们在代码中定义的方法而非编译器为我们生成的方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//6. 如果重写了父类的方法,则使用子类的
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
//如果是javax.xml.ws.WebServiceRef的类的处理 不需要关注
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
//如果是javax.ejb.EJB的类的处理 不需要关注
} else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
//7. 检查方法上是否有Resource注解
} else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
//7.1 如果Resource对应的方法是静态的直接报错
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
//7.2 获取对应方法的参数
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
//7.3 如果ignoredResourceTypes中没有对应入参的类型
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
//7.3.1 根据方法找到对应方法的属性
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
//7.3.2 封装成ResourceElement并添加到currElements
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
//8. 将所有的currElements添加到elements中
elements.addAll(0, currElements);
//9. 将targetClass的父类赋值给targetClass
targetClass = targetClass.getSuperclass();
}
//10. 如果targetClass不是object继续循环
while (targetClass != null && targetClass != Object.class);
//11. 将elements封装成InjectionMetadata并返回
return InjectionMetadata.forElements(elements, clazz);
}

​ 上述代码是将@Resource注解的字段和方法以bean name为key,InjectedElement为value封装一个Map中,在属性注入阶段取出InjectedElement通过反射为目标字段或方法设置@Resource name指定的bean。InjectionMetadata封装的是一组InjectionMetadata.InjectedElement,这个InjectedElement会使用inject方法完成依赖注入,具体下面会讲到。

doWithLocalFields

获取所有的字段信息并进行回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Invoke the given callback on all locally declared fields in the given class.
* 获取所有的字段信息并进行回调
*
*/
public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
//1. 获取class所有的字段信息并进行遍历
for (Field field : getDeclaredFields(clazz)) {
try {
//2. 调用回调方法
fc.doWith(field);
} catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
}
}
}

getDeclaredFields

获取clazz的所有的字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* This variant retrieves {@link Class#getDeclaredFields()} from a local cache
* in order to avoid the JVM's SecurityManager check and defensive array copying.
* 获取clazz的所有的字段
*
*/
private static Field[] getDeclaredFields(Class<?> clazz) {
Assert.notNull(clazz, "Class must not be null");
//1. 从缓存中获取字段
Field[] result = declaredFieldsCache.get(clazz);
if (result == null) {
try {
//2. 获取class的所有字段信息
result = clazz.getDeclaredFields();
//3. 放进缓存中
declaredFieldsCache.put(clazz, (result.length == 0 ? EMPTY_FIELD_ARRAY : result));
} catch (Throwable ex) {
throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() +
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
}
}
//4. 返回
return result;
}

checkConfigMembers

检测ConfigMembers并将InjectedElement集合赋值给全局的checkedElements

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 检测ConfigMembers并将InjectedElement集合赋值给全局的checkedElements
*
* @param beanDefinition
*/
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
//1. initMethod方法的检查以及设置
//遍历检查所有的收集的injectedElement元素
for (InjectedElement element : this.injectedElements) {
Member member = element.getMember();
// 2.如果beanDefinition的externallyManagedConfigMembers属性不包含该member
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
// 3.将该member添加到beanDefinition的externallyManagedConfigMembers属性
beanDefinition.registerExternallyManagedConfigMember(member);
// 4.并将element添加到checkedElements
checkedElements.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
//5. 对checkedElements进行赋值
this.checkedElements = checkedElements;
}

小结

到这里已经完成了对@Resource字段和方法的搜集,等待后面的注入

postProcessBeforeInitialization

bean会经过BeanPostProcessor.postProcessBeforeInitialization()方法处理,这个时候就会调用由@PostConstruct方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 实例化后调用initMethod
*
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//1. 从上一步搜集到的LifecycleMetadata中获取metadata
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//2. 调用InitMethod
metadata.invokeInitMethods(bean, beanName);
} catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}

invokeInitMethods

调用搜集到的由@PostConstruct的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 调用initMethod

*/
public void invokeInitMethods(Object target, String beanName) throws Throwable {
//1. 获取搜集的并检查过的checkedInitMethods
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
//2. 如果checkedInitMethods为空就选择initMethods
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
//3. 如果都不为空
if (!initMethodsToIterate.isEmpty()) {
//4. 遍历initMethodsToIterate并进行调用
for (LifecycleElement element : initMethodsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
//5. 反射调用
element.invoke(target);
}
}
}

依赖注入

对@Resources进行依赖注入

postProcessProperties

对@Resources进行依赖注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 进行依赖注入 @Resources注解
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//1. 查找@Resources注解 因为上一步已经搜集过了所以直接从缓存中拿取
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
//2. 进行依赖注入
metadata.inject(bean, beanName, pvs);
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}

inject

进行依赖注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 进行依赖注入
*
*/
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//1. 从checkedElements中获取需要注入的元素
Collection<InjectedElement> checkedElements = this.checkedElements;
//2. 如果checkedElements存在,则使用checkedElements,否则使用injectedElements
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
//3. 遍历需要注入的元素
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
//4.进行依赖注入
element.inject(target, beanName, pvs);
}
}
}
ResourceElement

依次调用之前保存的ResouceElement对象的inject方法。下面的重点就是放到了ResouceElement身上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* Class representing injection information about an annotated field
* or setter method, supporting the @Resource annotation.
*/
private class ResourceElement extends LookupElement {

private final boolean lazyLookup;

//根据上面分析有两种调用构造方法的情况
//1、member是字段ae也是字段,pd==null
//2、member是桥接方法(或原始方法)ae是原始方法,pd是原始方法的getter或setter
public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
super(member, pd);
Resource resource = ae.getAnnotation(Resource.class);
String resourceName = resource.name();
Class<?> resourceType = resource.type();
this.isDefaultName = !StringUtils.hasLength(resourceName);
if (this.isDefaultName) {
///如果没有设置@Resource name属性就用字段名称作为bean name
resourceName = this.member.getName();
//如果member是setter方法方法 则取setXXX得XXX部分为bean name
if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
resourceName = Introspector.decapitalize(resourceName.substring(3));
}
} else if (embeddedValueResolver != null) {
//如果设置了@Resource name的属性,则使用EmbeddedValueResolver对象先做一次SpringEL解析得到真正的bean name
resourceName = embeddedValueResolver.resolveStringValue(resourceName);
}
if (Object.class != resourceType) {
//确保字段或setter方法类型与resourceType一致
checkResourceType(resourceType);
} else {
// No resource type specified... check field/method.
resourceType = getResourceType();
}
this.name = (resourceName != null ? resourceName : "");
this.lookupType = resourceType;
String lookupValue = resource.lookup();
//如果使用jndi查找的名字
this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
Lazy lazy = ae.getAnnotation(Lazy.class);
//是否延迟注入
this.lazyLookup = (lazy != null && lazy.value());
}

//如果懒加载则使用一个代理对象,往下看
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
}

​ 从上面CommonAnnotationBeanPostProcessor的postProcessProperties()方法可知,属性的注入是调用ResourceElement的inject()方法,ResourceElement本身没有这个方法而是调用父类InjectedElement的inject方法。

InjectionMetadata.inject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
//如果是字段类型
if (this.isField) {
Field field = (Field) this.member;
//设置该字段可以访问
ReflectionUtils.makeAccessible(field);
//字段set进行注入
//如果是使用字段形式的注入,getResourceToInject由子类@ResourceElement实现,下面再看
field.set(target, getResourceToInject(target, requestingBeanName));
} else {
//此步骤检测如果bean已经显示的设置一个对象依赖引用则跳过使用setter方法再次赋值。
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
//支持私有方法
ReflectionUtils.makeAccessible(method);
//反射调用方法进行注入
method.invoke(target, getResourceToInject(target, requestingBeanName));
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}

​ 可以看到需要注入对象的来源方法getResourceToInject(),上面已经看到如果懒加载则使用buildLazyResourceProxy()方法将返回一个代理对象,等到使用到这个代理对象的方法时才会调用getResource()返回requestingBeanName指定的bean。下面先看getResource()方法。

getResource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Obtain the resource object for the given name and type.
* 获取给定名称和类型的资源对象。
*
*/
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
//1. 如果有lookup字段
if (StringUtils.hasLength(element.mappedName)) {
//1.1 创建并返回bena的实例
return this.jndiFactory.getBean(element.mappedName, element.lookupType);
}
//2. 如果使用了jndi的lookUp
if (this.alwaysUseJndiLookup) {
//2.1 创建并返回bena的实例
return this.jndiFactory.getBean(element.name, element.lookupType);
}
//3. 如果resourceFactory为空直接报错
if (this.resourceFactory == null) {
throw new NoSuchBeanDefinitionException(element.lookupType,
"No resource factory configured - specify the 'resourceFactory' property");
}
//4. 返回注入的resources
return autowireResource(this.resourceFactory, element, requestingBeanName);
}

autowireResource

获取需要@Resources注入的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* Obtain a resource object for the given name and type through autowiring
* based on the given factory.
* <p>
* 获取需要@Resources注入的对象
*/
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {

Object resource;
Set<String> autowiredBeanNames;
String name = element.name;
//1. 如果是AutowireCapableBeanFactory类型的工厂
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
//2. 如果容器中还没有此bean,则会使用resolveDependency()方法将符合bean type的bean definetion调用一次getBean()从这些bean选出符合requestingBeanName的bean
autowiredBeanNames = new LinkedHashSet<>();
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
if (resource == null) {
throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
}
} else {
//3. 如果容器中有此bean则取出这个bean对象作为属性值
resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
} else {
//4. 调用getBean来获取实例
resource = factory.getBean(name, element.lookupType);
autowiredBeanNames = Collections.singleton(name);
}
//5. 如果是ConfigurableBeanFactory类型的
if (factory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
//6. 遍历注入bean的名称
for (String autowiredBeanName : autowiredBeanNames) {
//7. 如果传入的beanName不为空且包含对应的名称
if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
//8. 注册依赖的bean和bean name的映射关系
beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
}
}
}

return resource;
}
buildLazyResourceProxy

包装延迟加载对象 传入一个需要延时调用方法,并生成代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* Obtain a lazily resolving resource proxy for the given name and type,
* delegating to {@link #getResource} on demand once a method call comes in.
* 包装延迟加载对象 传入一个需要延时调用方法,并生成代理
*
*/
protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) {
TargetSource ts = new TargetSource() {
@Override
public Class<?> getTargetClass() {
return element.lookupType;
}

@Override
public boolean isStatic() {
return false;
}

@Override
public Object getTarget() {
//这个方法里还是会调用getResource(),什么时候调用的getTarget()方法呢,往下看
return getResource(element, requestingBeanName);
}

@Override
public void releaseTarget(Object target) {
}
};
//代理对象工厂
ProxyFactory pf = new ProxyFactory();
pf.setTargetSource(ts);
if (element.lookupType.isInterface()) {
pf.addInterface(element.lookupType);
}
ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null);
return pf.getProxy(classLoader);
}

​ 这个方法大段代码是为了实现AOP,但还是会调用target = targetSource.getTarget();获取实际对象的,可以看到懒加载机制的代理对象只有调用其方法才会去容器中获取实际的bean。

对象销毁

调用有@Destroy注解的销毁方法

postProcessBeforeDestruction

在bean销毁前会经过DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()方法,在这个时候执行@PreDestroy方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 调用有@Destroy注解的销毁方法
*
* @param bean
* @param beanName
* @throws BeansException
*/
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
//获取对应bean的metadata
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//调用销毁方法
metadata.invokeDestroyMethods(bean, beanName);
} catch (InvocationTargetException ex) {
String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex.getTargetException());
} else {
logger.warn(msg + ": " + ex.getTargetException());
}
} catch (Throwable ex) {
logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
}
}

invokeDestroyMethods

调用销毁方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 调用销毁方法
*/
public void invokeDestroyMethods(Object target, String beanName) throws Throwable {
//1. 获取销毁方法对象的列表
Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods;
//2. 如果checkedDestroyMethods为空就选择destroyMethods
Collection<LifecycleElement> destroyMethodsToUse =
(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
if (!destroyMethodsToUse.isEmpty()) {
//3. 遍历所有的元素
for (LifecycleElement element : destroyMethodsToUse) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy method on bean '" + beanName + "': " + element.getMethod());
}
//4. 反射进行调用
element.invoke(target);
}
}
}

评论