在《spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)》一文中,分析到在调用CommonAnnotationBeanPostProcessor类的postProcessMeredBeanDefinition方法时会先调用其父类的postProcessMeredBeanDefinition方法,下面就来分析CommonAnnotationBeanPostProcessor类的父类InitDestroyAnnoatationBeanPostProcessor。
一、概述
我们先看下CommonAnnotationAnnotationBeanPostProcessor类,上篇中介绍到该类有一个静态代码块会在类初始化的时候调用,在该类中还有一个默认的构造函数,
public CommonAnnotationBeanPostProcessor() { setOrder(Ordered.LOWEST_PRECEDENCE - 3); //@PostConstruct注解,作用在方法上 setInitAnnotationType(PostConstruct.class@PreDestroy注解,作用在方法上 setDestroyAnnotationType(PreDestroy.); ignoreResourceType("javax.xml.ws.WebServiceContext"); }
该构造函数中分别调用了setInitAnnotationType和setDestroyAnnotationType方法,两个方法分别调用其父类的方法,
/** * Specify the init annotation to check for,indicating initialization * methods to call after configuration of a bean. * <p>Any custom annotation can be used,since there are no required * annotation attributes. There is no default,although a typical choice * is the JSR-250 {@link javax.annotation.PostConstruct} annotation. */ public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) { this.initAnnotationType = initAnnotationType; } * Specify the destroy annotation to check for,indicating destruction * methods to call when the context is shutting down. * <p>Any custom annotation can be used,1)"> javax.annotation.PreDestroy} annotation. void setDestroyAnnotationType(Class<? destroyAnnotationType) { this.destroyAnnotationType = destroyAnnotationType; }
分别给的InitDestroyAnnotationBeanPostProcessor的initAnnotationType和destroyAnnotationType赋值@PostConstruct和@PreDestroy注解。
二、详述
上面提到在调用CommonAnnotationBeanPostProcessor类的postProcessMeredBeanDefinition方法时会先调用父类的方法,下面看CommonAnnotationBeanPostProcessor的方法,
@Override void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class<?> beanType,String beanName) { super.postProcessMergedBeanDefinition(beanDefinition,beanType,beanName); InjectionMetadata metadata = findResourceMetadata(beanName,null); metadata.checkConfigMembers(beanDefinition); }
上面是CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,可以看到调用了父类的postProcessMergedBeanDefinition方法,其他的方法在上篇博客中已经分析,来重点分析InitDestroyAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,
findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
在方法中调用了findLifecycleMetadata和checkConfigMembers方法,
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) { 判断lifecycleMetadataCache是否为空 if (this.lifecycleMetadataCache == ) { Happens after deserialization,during destruction... return buildLifecycleMetadata(clazz); } Quick check on the concurrent map first,with minimal locking. 从lifecycleMetadataCache中取,如果存在则直接返回,不存在则生成一个LifecycleMetadata对象并返回 LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz); if (metadata == synchronized (.lifecycleMetadataCache) { metadata = .lifecycleMetadataCache.get(clazz); ) { metadata = buildLifecycleMetadata(clazz); .lifecycleMetadataCache.put(clazz,metadata); } metadata; } } metadata; }
在findLifecycleMetadata方法中主要调用的是buildLifecycleMetadata方法,改方法的返回值是LifecycleMetadata对象,之后把该对象放到lifecycleMetadataCache中,那么这里lifecycleMetadata应该是Map类型的,
@Nullable private final transient Map<Class<?>,LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256);
buildLifecycleMetadataf方法如下,
private LifecycleMetadata buildLifecycleMetadata(final Class<?>if (!AnnotationUtils.isCandidateClass(clazz,Arrays.asList(this.initAnnotationType,1)">.destroyAnnotationType))) { return .emptyLifecycleMetadata; } List<LifecycleElement> initMethods = new ArrayList<>(); List<LifecycleElement> destroyMethods = (); Class<?> targetClass = clazz; do { final List<LifecycleElement> currInitMethods = (); final List<LifecycleElement> currDestroyMethods = (); 判断方法上是否存在initAnnotationType的注解,这里指的就是@PostConstruct注解 ReflectionUtils.doWithLocalMethods(targetClass,method -> { this.initAnnotationType != null && method.isAnnotationPresent(.initAnnotationType)) { LifecycleElement element = new LifecycleElement(method); currInitMethods.add(element); if (logger.isTraceEnabled()) { logger.trace("Found init method on class [" + clazz.getName() + "]: " + method); } } 判断方法上是否存在destroyAnnotationType的注解,这里指的就是@PreDestroy注解 this.destroyAnnotationType != .destroyAnnotationType)) { currDestroyMethods.add( LifecycleElement(method)); (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.); return (initMethods.isEmpty() && destroyMethods.isEmpty() ? .emptyLifecycleMetadata : LifecycleMetadata(clazz,initMethods,destroyMethods)); }
从上面的分析,可以知道InitDestroyAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法完成的功能就是把类中含有@PostConstrunct和@PreDestroy注解的方法信息缓存到lifecycleMetadataCache中。也就是说在一个被spring管理的类中允许定义被这两个注解修饰的方法,那方法有那些要求那,看上面的new LifecycleElement这里,看LifecycleElement类
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()); }
看上面的异常,意思是不允许此类方法有方法参数,如果有参数则会抛异常。
三、使用场景
上面分析了InitDestroyAnnotationBeanPostProcessor类中postProcessMergedBeanDefinition方法的作用,就是把类中有@PostConstruct、@PreDestroy两个注解的方法信息进行缓存,至于这两个注解的作用及被这两个注解标记的方法何时调用后面会继续分析。
原创不易,有不正之处欢迎指正。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。