前言
CommonAnnotationBeanPostProcessor这个BeanPostProcessor通过继承InitDestroyAnnotationBeanPostProcessor对@javax.annotation.PostConstruct和@javax.annotation.PreDestroy注解的支持。以及依据bean name依赖注入的@javax.annotation.Resource支持。也支持WebServiceRef注解,具有创建JAX-WS服务端点的能力。最后,处理器还支持EJB3(@EJB)。
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
@Nullable
private static Class<? extends Annotation> webServiceRefClass;
@Nullable
private static Class<? extends Annotation> ejbRefClass;
private final Set<String> ignoredResourceTypes = new HashSet<>(1);
private boolean fallbackToDefaultTypeMatch = true;
private boolean alwaysUseJndiLookup = false;
private transient BeanFactory jndiFactory = new SimpleJndiBeanFactory();
@Nullable
private transient BeanFactory resourceFactory;
@Nullable
private transient BeanFactory beanFactory;
@Nullable
private transient StringValueResolver embeddedValueResolver;
private final transient Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
static {
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());
webServiceRefClass = clazz;
}
catch (ClassNotFoundException ex) {
webServiceRefClass = null;
}
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());
ejbRefClass = clazz;
}
catch (ClassNotFoundException ex) {
ejbRefClass = null;
}
}
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
}
一、注解信息读取和包装
CommonAnnotationBeanPostProcessor
继承了InitDestroyAnnotationBeanPostProcessor
,这两个注解是由这个父类完成解析的,在CommonAnnotationBeanPostProcessor
构造函数中调用父类的方法setInitAnnotationType()和setDestroyAnnotationType()将这两个注解Class对象传递给父类。
在InitDestroyAnnotationBeanPostProcessor
中分三个阶段完成这两个注解功能,分别为:
CommonAnnotationBeanPostProcessor是一个InstantiationAwareBeanPostProcessor,但其postProcessBeforeInstantiation返回为null,所以他不行影响spring内部正常的bean实例化流程。在调用bean的构造器后,又因为其是一个MergedBeanDefinitionPostProcessor,所以他会执行其postProcessMergedBeanDefinition方法。CommonAnnotationBeanPostProcessor是在postProcessMergedBeanDefinition方法中完成了其对
@PostConstruct
和@PreDestroy
,@Resource注解的处理
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
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);
}
}
1.1 对@PostConstruct和@PreDestroy注解信息的读取
public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
//CommonAnnotationBeanPostProcessor在初始化时向里面放置了@PostConstruct注解
private Class<? extends Annotation> initAnnotationType;
//CommonAnnotationBeanPostProcessor在初始化时向里面放置了@PreDestroy注解
private Class<? extends Annotation> destroyAnnotationType;
@Nullable
private final transient Map<Class<?>, LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256);
@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) {
// 在反序列化之后,在销毁期间。。。
return buildLifecycleMetadata(clazz);
}
// 首先对并发映射进行快速检查,只需最少的锁定。
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;
}
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
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对象,储存起来
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
}
//查看方法上是否有@PreDestroy注解存在
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
//如果有把他封装成LifecycleElement对象,储存起来
currDestroyMethods.add(new LifecycleElement(method));
}
});
// 初始化方法父类早于子类
initMethods.addAll(0, currInitMethods);
// 销毁方法父类晚于子类
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
//把他们封装成LifecycleMetadata对象
return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
把@PostConstruct和@PreDestroy注解信息和其方法信息包装成LifecycleMetadata存储到lifecycleMetadataCache中
private class LifecycleMetadata {
private final Class<?> targetClass;
private final Collection<LifecycleElement> initMethods;
private final Collection<LifecycleElement> destroyMethods;
1.2 对@Resource注解的处理
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
private final transient Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
@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);
}
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, PropertyValues pvs) {
//退回到类名作为缓存键,以便与自定义调用者向后兼容。
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
//先根据键值从缓存injectionMetadataCache中查询对应的InjectionMetadata
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
//如果metadata为null
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(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//处理属性上的注解
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 (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));
}
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));
}
}
});
//处理方法上的注解
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 (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));
}
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 new InjectionMetadata(clazz, elements);
}
@Resource如果遇到static属性或者方法,他是直接报错,@Autowired如果遇到static属性或者方法,他是不会处理
CommonAnnotationBeanPostProcessor把@Resource属性或者方法都包装成ResourceElement,而AutowiredAnnotationBeanPostProcessor把@Autowired属性包装成AutowiredFieldElement,@Autowired方法包装成AutowiredMethodElement
二、@Resource属性赋值
地点发生在populateBean()方法,因为其方法postProcessAfterInstantiation()返回的是true,所以他会调用其postProcessProperties方法为bean赋值属性,其对@Resource属性赋值或者方法的执行都发生在这
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
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;
}
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);
}
}
}
}
底层执行的是ResourceElement的inject方法,但ResourceElement没有重写其父类InjectedElement的inject方法,所以执行的方法还是其父类的
public class InjectionMetadata {
public abstract static class InjectedElement {
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);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}
}
三、@PostConstruct和@PreDestroy标注方法的执行
在initializeBean()方法中,因为其是一个先执行其BeanPostProcessor,所以他会先执行其postProcessBeforeInitialization,在调用其初始化方法,在调用其postProcessAfterInitialization,这里先说明下,其postProcessAfterInitialization方法没有做任何处理,@PostConstruct和@PreDestroy标注方法的执行发生在postProcessBeforeInitialization方法中,
public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
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());
}
//其底层代码如下
//ReflectionUtils.makeAccessible(this.method);
//this.method.invoke(target, (Object[]) null);
element.invoke(target);
}
}
}
}
其是在这边我们可以看出,@PostConstruct和@PreDestroy标注的方法执行顺序,先于通过实现 InitializingBean/DisposableBean 接口来定制的初始化之后/销毁方法。
@Component
public class Child implements InitializingBean {
@PostConstruct
public void init(){
System.out.println("通过@PostConstruct指定的初始化方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("通过实现InitializingBean接口指定的初始化方法");
}
}
通过@PostConstruct指定的初始化方法
通过实现InitializingBean接口指定的初始化方法