CommonAnnotationBeanPostProcessor间接实现了BeanPostProcessor接口,属于Spring中的一个扩展,主要用于处理 @PostConstruct、@PreDestroy、@Resource 等常用注解。其关系如下图。
一、案例准备
1、配置类
package com.example.demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.example.demo")
@Configuration
public class AppConfiguration {
}
2、实体类
package com.example.demo.entity;
import java.io.Serializable;
@Data
public class User implements Serializable {
private Long id;
private String name;
private Integer age;
}
3、业务逻辑类
package com.example.demo.service.impl;
import com.example.demo.service.MenuService;
import com.example.demo.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
@Service
public class MenuServiceImpl implements MenuService {
@Resource
private RoleService roleService;
@PostConstruct
public void testPostConstruct() {
System.out.println("== PostConstruct ==");
}
@PreDestroy
public void testPreDestroy() {
System.out.println("== PreDestroy ==");
}
@Override
public void print() {
System.out.println("MenuServiceImpl");
}
}
--------------------------------------------------------------
package com.example.demo.service.impl;
import com.example.demo.service.RoleService;
import org.springframework.stereotype.Service;
@Service
public class RoleServiceImpl implements RoleService {
@Override
public void print() {
System.out.println("RoleServiceImpl");
}
}
4、测试类
package com.example.demo.main;
import com.example.demo.config.AppConfiguration;
import com.example.demo.service.impl.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfiguration.class);
applicationContext.refresh();
MenuServiceImpl menuService = applicationContext.getBean(MenuServiceImpl.class);
menuService.print();
// 这里需要显式调用一下,用于测试 @PreDestroy 注解的方法调用
applicationContext.close();
}
}
二、源码解析(基于Spring-5.3.32版本)
1、关键处理方法
(1)org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
把加了 @Resource 注解的属性和方法,以及加了 @PostConstruct 和 @PreDestroy 的方法全部找出并缓存。
(2)org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessProperties
对加了 @Resource 注解的属性和方法进行处理,若为属性则反射注入,若为方法则反射调用。
(3)org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
初始化前执行加了 @PostConstruct 注解的方法
(4)org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
销毁前执行加了 @PreDestroy 注解的方法
2、源码分析
(1)org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
从 applyMergedBeanDefinitionPostProcessors 方法开始,该方法会将加了 @Resource 注解的属性和方法,以及加了 @PostConstruct 和 @PreDestroy 的方法全部找出并缓存。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
......省略
......省略
......省略
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 循环后置处理器,并调用各自的实现
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
......省略
......省略
......省略
}
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
// processor 为 CommonAnnotationBeanPostProcessor,断点进入调试
// 将加了 @PostConstruct、@PreDestroy、@Resource 注解的方法全部找出并缓存
processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
(2)org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition(查找并缓存@Resource、@PostConstruct、@PreDestroy)
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 查找加了 @PostConstruct 和 @PreDestroy 的方法并缓存
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// 查找加了 @Resource 的属性和方法并缓存
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
// 校验查找结果
metadata.checkConfigMembers(beanDefinition);
}
// 下面文章会分别根据上面三段代码进行分析,考虑到阅读体验,只保留关键代码,所以想知道细节的还是要自己花时间调试。
postProcessMergedBeanDefinition
// 主要看 buildLifecycleMetadata 方法
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
----------------------------------------------------------------------------
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
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) {
// 找出结果并封装到 LifecycleMetadata 中
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
----------------------------------------------------------------------------
// 重点
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
// 对实例化对象中的方法进行处理
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 找出所有加了 @PostConstruct 的方法
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
// 找出所有加了 @PreDestroy 的方法
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
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();
}
while (targetClass != null && targetClass != Object.class);
// 将结果放入到 LifecycleMetadata 实例中
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
----------------------------------------------------------------------------
// 下面两个方法主要让你知道 this.injectedElements 是在这里赋值的
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
// 加了注解后 elements 一般不为空
return (elements.isEmpty() ? new InjectionMetadata(clazz, Collections.emptyList()) :
new InjectionMetadata(clazz, elements));
}
public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {
this.targetClass = targetClass;
// 关键点
this.injectedElements = elements;
}
至于 this.initAnnotationType 和 this.destroyAnnotationType 的赋值操作,则是在实例化 CommonAnnotationBeanPostProcessor 时做的。如下代码。
// CommonAnnotationBeanPostProcessor 构造器
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
// 给 this.initAnnotationType 赋值
setInitAnnotationType(PostConstruct.class);
// 给 this.destroyAnnotationType 赋值
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
// java.naming module present on JDK 9+?
if (jndiPresent) {
this.jndiFactory = new SimpleJndiBeanFactory();
}
}
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
this.initAnnotationType = initAnnotationType;
}
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
this.destroyAnnotationType = destroyAnnotationType;
}
findResourceMetadata
private InjectionMetadata findResourceMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
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);
}
// 构建 Resource 元数据
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
----------------------------------------------------------------------------
// 下面这段代码有点长,但其实很简单
private InjectionMetadata buildResourceMetadata(Class<?> clazz) {
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<>();
// 处理属性
// 找出加了 @WebServiceRef @EJB @Resource 等注解的属性,并存放到 currElements 中
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");
}
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
// 处理方法
// 找出加了 @WebServiceRef @EJB @Resource 等注解的方法,并存放到 currElements 中
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
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 (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
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));
}
}
// 常用的一个注解 @Resource
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// @Resource不支持静态方法
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
// @Resource作用的方法只能有一个参数
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);
}
----------------------------------------------------------------------------
// 为了方便阅读,这段复制了一份
// 下面两个方法主要让你知道 this.injectedElements 是在这里赋值的
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
// 加了注解后 elements 一般不为空
return (elements.isEmpty() ? new InjectionMetadata(clazz, Collections.emptyList()) :
new InjectionMetadata(clazz, elements));
}
public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {
this.targetClass = targetClass;
// 关键点
this.injectedElements = elements;
}
checkConfigMembers
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
// this.injectedElements 取值看上面
Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
for (InjectedElement element : this.injectedElements) {
Member member = element.getMember();
// 去除重复值
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
beanDefinition.registerExternallyManagedConfigMember(member);
checkedElements.add(element);
}
}
// 最终结果
this.checkedElements = checkedElements;
}
小结:加了 @Resource 的属性和方法会缓存到 this.injectedElements 中,加了 @PostConstruct 注解的方法会缓存到 this.initMethods,加了 @PreDestroy 注解的方法会缓存到 this.destroyMethods。(this.checkedElements
变量在 org.springframework.beans.factory.annotation.InjectionMetadata 中;this.checkedInitMethods
和 this.checkedDestroyMethods
变量在 org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata 中。
(3)org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(处理@Resource)
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
......省略
......省略
......省略
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// CommonAnnotationBeanPostProcessor 对 @Resource 注解进行处理
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
......省略
......省略
......省略
}
----------------------------------------------------------------------------
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 从缓存中取出加了 @Resource 注解的属性和方法的元数据
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;
}
----------------------------------------------------------------------------
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) {
// 循环反射处理
element.inject(target, beanName, pvs);
}
}
}
----------------------------------------------------------------------------
// 到这一步就很清晰明了了
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
// 判断是否为属性
if (this.isField) {
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
// 通过反射为属性赋值
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
if (checkPropertySkipping(pvs)) {
return;
}
try {
Method method = (Method) this.member;
ReflectionUtils.makeAccessible(method);
// java 中的方法反射
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
(4)org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(处理@PostConstruct)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
......省略
......省略
......省略
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化之前执行后置处理器的方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
......省略
......省略
......省略
return wrappedBean;
}
----------------------------------------------------------------------------
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 循环后置处理器,在初始化之前执行相应后置处理器的方法
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
----------------------------------------------------------------------------
// @PostConstruct 和 @PreDestroy 的处理都在 InitDestroyAnnotationBeanPostProcessor 中
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 从缓存中取出加了 @PostConstruct 注解的方法元数据
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 反射调用
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;
}
----------------------------------------------------------------------------
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
for (LifecycleElement element : initMethodsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
// 反射调用 @PostConstruct 注解方法
element.invoke(target);
}
}
}
// 这一步就很明了,java中的方法反射
public void invoke(Object target) throws Throwable {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(target, (Object[]) null);
}
(5)org.springframework.beans.factory.support.DisposableBeanAdapter#destroy(处理@PreDestroy)
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
// 后置处理器方法调用
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
......省略
......省略
......省略
}
----------------------------------------------------------------------------
// InitDestroyAnnotationBeanPostProcessor 中的方法 postProcessBeforeDestruction
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
// 获取缓存中加了 @PreDestroy 注解的方法元数据
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);
}
}
----------------------------------------------------------------------------
public void invokeDestroyMethods(Object target, String beanName) throws Throwable {
// 加了 @PreDestroy 注解的方法的缓存
Collection<LifecycleElement> checkedDestroyMethods = this.checkedDestroyMethods;
Collection<LifecycleElement> destroyMethodsToUse =
(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
if (!destroyMethodsToUse.isEmpty()) {
for (LifecycleElement element : destroyMethodsToUse) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy method on bean '" + beanName + "': " + element.getMethod());
}
// 反射调用加了 @PreDestroy 注解的方法
element.invoke(target);
}
}
}
// java中的方法反射
public void invoke(Object target) throws Throwable {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(target, (Object[]) null);
}