Spring系列-3.4 CommonAnnotationBeanPostProcessor
Spring版本:Spring 5.2.9.BUILD-SNAPSHOT
修改过部分源码,但不影响主体流程
概述
CommonAnnotationBeanPostProcessor负责解析@Resource
、@WebServiceRef
、@EJB
、@PostConstruct
、@PreDestroy
注解,这几个注解都是定义在javax.*
包下的注解,属于java
中的注解。
类图
InstantiationAwareBeanPostProcessor
提供了bean
实例化前后对bean
的操作以及在属性赋值前,传递属性值的postProcessProperties
方法。
InitDestroyAnnotationBeanPostProcessor
继承了DestructionAwareBeanPostProcessor
和MergedBeanDefinitionPostProcessor
接口。
主要实现的方法有:postProcessMergedBeanDefinition
、postProcessBeforeInitialization
、postProcessBeforeDestruction
、requiresDestruction
。
MergedBeanDefinitionPostProcessor
用于处理合并后的BeanDefinition
,在bean
实例化后、属性赋值前回调。
DestructionAwareBeanPostProcessor
用于bean
销毁前的回调。
注册时机
AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry, Object)
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
// 注册内部管理的用于处理JSR-250注解,例如@Resource,@PostConstruct,@PreDestroy的后置处理器bean
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
源码解析
postProcessMergedBeanDefinition
-
处理
@PostConstruct
和@PreDestroy
注解。 -
找出
beanType
所有被@Resource
、@WebServiceRef
、@EJB
标记的字段和方法封装到InjectionMetadata
中。
调用时机
doCreateBean
-> applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
-> bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName)
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 处理@PostConstruct和@PreDestroy注解
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
//找出beanType所有被@Resource标记的字段和方法封装到InjectionMetadata中
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
postProcessMergedBeanDefinition
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 调用方法获取生命周期元数据并保存
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
// 验证相关方法
metadata.checkConfigMembers(beanDefinition);
}
-
找到该类型的
LifecycleMetadata
数据,如果没有则会新增一份放到lifecycleMetadataCache
中。 -
从找到的
LifecycleMetadata
,执行其checkConfigMembers
进行类型检查,将上一步找到的符合条件的方法,冗余一份到BeanDefinition
中。
findLifecycleMetadata
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
// 在bean销毁过程中,反序列化后调用
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
// 首先尝试从缓存中获取元数据
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
// 如果从缓存中获取失败则尝试加锁创建元数据
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
// 加锁后再次尝试获取元数据,防止多线程重复执行
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
// 构建生命周期元数据
metadata = buildLifecycleMetadata(clazz);
// 将构建好的元数据放入缓存中
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
buildLifecycleMetadata
/**
* 构造生命周期元数据(解析带@PostConstruct和@PreDestroy注解的方法),当其构造完成后会将元数据缓存到lifecycleMetadataCache集合中并返回
* 此时就完成了相关方法(初始化方法和销毁方法)的扫描解析和缓存工作
*
* @param clazz
* @return
*/
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
// 实例化后的回调方法(@PostConstruct)
List<LifecycleElement> initMethods = new ArrayList<>();
// 销毁前的回调方法(@PreDestroy)
List<LifecycleElement> destroyMethods = new ArrayList<>();
// 获取正在处理的目标类
Class<?> targetClass = clazz;
do {
// 保存每一轮循环搜索到的相关方法
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
// 反射获取当前类中的所有方法并依次对其调用第二个参数的lambda表达式
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 当前方法的注解中包含initAnnotationType注解时(@PostConstruct)
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
// 如果有,把它封装成LifecycleElement对象,存储起来
LifecycleElement element = new LifecycleElement(method);
// 将创建好的元素添加到集合中
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
// 当前方法的注解中包含destroyAnnotationType注解(PreDestroy)
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
// 如果有,把它封装成LifecycleElement对象,存储起来
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
// 将本次循环中获取到的对应方法集合保存到总集合中
initMethods.addAll(0, currInitMethods);
// 销毁方法父类晚于子类
destroyMethods.addAll(currDestroyMethods);
// 获取当前类的父类
targetClass = targetClass.getSuperclass();
}
// 如果当前类存在父类且父类不为object基类则循环对父类进行处理
while (targetClass != null && targetClass != Object.class);
// 有一个不为空就封装一个LifecycleMetadata对象,否则就返回空的emptyLifecycleMetadata
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
-
遍历该
bean
的所有方法。 -
找到所有本类及父类的
@PostConstruct
注解和
@PreDestroy,并用他们构造
LifecycleMetadata`并返回。
findResourceMetadata
/**
* 解析@Resource注解
* @param beanName
* @param clazz
* @param pvs
* @return
*/
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.
// 获取对应的bean名称作为缓存key
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 从缓存中获取注入元数据对象
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 将返回的metadata对象放入injectionMetadataCache缓存中,缓存key为beanName,供后续方法从缓存中取出
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
- 从
injectionMetadataCache
获取缓存的对象,如果没找到走下面的方法并缓存到injectionMetadataCache
中
buildResourceMetadata
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
// 判断当前clazz是否是候选class
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
// 创建InjectedElement集合对象
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 查询是否有webService,ejb,Resource的属性注解,但是不支持静态属性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
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));
}
else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
//注意静态字段不支持
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
//如果不想注入某一类型对象 可以将其加入ignoredResourceTypes中
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
//字段会封装到ResourceElement
currElements.add(new ResourceElement(field, field, null));
}
}
});
// 处理方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//找出我们在代码中定义的方法而非编译器为我们生成的方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//如果重写了父类的方法,则使用子类的
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
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));
}
else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
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));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
// 不支持静态方法
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
-
找到所有被
@WebServiceRef
、@EJB
、@Resource
注解修饰的字段(非静态)。 -
找到所有被
@WebServiceRef
、@EJB
、@Resource
注解修饰的方法(非静态)。 -
将上面两步找到的
metadata
数据,构造一个InjectionMetadata
返回并最终存到injectionMetadataCache
中。
@PostConstruct
调用时机
doCreateBean
-> initializeBean
-> applyBeanPostProcessorsBeforeInitialization
-> postProcessBeforeInitialization
-> invokeInitMethods
-> invoke
-
获取
LifecycleMetadata
缓存的方法数据。 -
反射调用方法。
@PreDestroy
调用时机
ac.close()
-> destroyBeans
-> processor.postProcessBeforeDestruction(this.bean, this.beanName);
-> invokeDestroyMethods
-> invoke
调用方式与@PostConstruct
差不多,都是通过BeanPostProcessor
后置处理器前置、后置方法调用实现的。
@Resource
@Resource
调用方式和@Autowired
差不多。
@Autowired
详细流程可参考Spring系列-3.3 AutowiredAnnotationBeanPostProcessor
调用时机
doCreateBean
->populateBean
->postProcessProperties
postProcessProperties
/**
* 处理注入注解元数据
* @param pvs the property values that the factory is about to apply (never {@code null})
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
}
return pvs;
}
findResourceMetadata
/**
* 解析@Resource注解
* @param beanName
* @param clazz
* @param pvs
* @return
*/
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.
// 获取对应的bean名称作为缓存key
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 从缓存中获取注入元数据对象
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 将返回的metadata对象放入injectionMetadataCache缓存中,缓存key为beanName,供后续方法从缓存中取出
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
buildResourceMetadata
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
// 判断当前clazz是否是候选class
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
// 创建InjectedElement集合对象
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 查询是否有webService,ejb,Resource的属性注解,但是不支持静态属性
ReflectionUtils.doWithLocalFields(targetClass, field -> {
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));
}
else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
//注意静态字段不支持
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
//如果不想注入某一类型对象 可以将其加入ignoredResourceTypes中
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
//字段会封装到ResourceElement
currElements.add(new ResourceElement(field, field, null));
}
}
});
// 处理方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//找出我们在代码中定义的方法而非编译器为我们生成的方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
//如果重写了父类的方法,则使用子类的
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
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));
}
else if (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {
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));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
// 不支持静态方法
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
metadata.inject(bean, beanName, pvs);
/**
* 遍历前面注册的InjectedElement,然后进行注入
* @param target
* @param beanName
* @param pvs
* @throws Throwable
*/
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
element.inject(target, beanName, pvs);
/**
* 进行属性或者方法注入,但是方法注入前会判断是否已经有设置值了,有设置就不会注入,直接返回
*
* Either this or {@link #getResourceToInject} needs to be overridden.
*/
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
// 属性注入
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
// 如果是使用字段形式的注入,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
/**
* 首先判断注释元数据有没有@Lazy注解,有的话就创建一个代理类,内部是用AOP代理工厂做的
* @param target
* @param requestingBeanName
* @return
*/
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
// 如果懒加载则使用一个代理对象
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
getResource(this, requestingBeanName));
}
- 这里处理了@Lazy注解,判断注释元数据有没有@Lazy注解,有的话就创建一个代理类,内部是用AOP代理工厂做的