spring中BeanPostProcessor之三:InitDestroyAnnotationBeanPostProcessor(01)
在《spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)》一文中,分析到在调用CommonAnnotationBeanPostProcessor类的postProcessMeredBeanDefinition方法时会先调用其父类的postProcessMeredBeanDefinition方法,下面就来分析CommonAnnotationBeanPostProcessor类的父类InitDestroyAnnoatationBeanPostProcessor。
一、概述
我们先看下CommonAnnotationAnnotationBeanPostProcessor类,上篇中介绍到该类有一个静态代码块会在类初始化的时候调用,在该类中还有一个默认的构造函数,
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
//@PostConstruct注解,作用在方法上
setInitAnnotationType(PostConstruct.class);
//@PreDestroy注解,作用在方法上
setDestroyAnnotationType(PreDestroy.class);
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, since there are no required
* annotation attributes. There is no default, although a typical choice
* is the JSR-250 {@link javax.annotation.PreDestroy} annotation.
*/
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
this.destroyAnnotationType = destroyAnnotationType;
}
分别给的InitDestroyAnnotationBeanPostProcessor的initAnnotationType和destroyAnnotationType赋值@PostConstruct和@PreDestroy注解。
二、详述
上面提到在调用CommonAnnotationBeanPostProcessor类的postProcessMeredBeanDefinition方法时会先调用父类的方法,下面看CommonAnnotationBeanPostProcessor的方法,
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
上面是CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,可以看到调用了父类的postProcessMergedBeanDefinition方法,其他的方法在上篇博客中已经分析,来重点分析InitDestroyAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
在方法中调用了findLifecycleMetadata和checkConfigMembers方法,
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
//判断lifecycleMetadataCache是否为空
if (this.lifecycleMetadataCache == null) {
// 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 == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
在findLifecycleMetadata方法中主要调用的是buildLifecycleMetadata方法,改方法的返回值是LifecycleMetadata对象,之后把该对象放到lifecycleMetadataCache中,那么这里lifecycleMetadata应该是Map类型的,
@Nullable
private final transient Map<Class<?>, LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256);
buildLifecycleMetadataf方法如下,
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<>();
//判断方法上是否存在initAnnotationType的注解,这里指的就是@PostConstruct注解
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
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);
}
}
//判断方法上是否存在destroyAnnotationType的注解,这里指的就是@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);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
从上面的分析,可以知道InitDestroyAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法完成的功能就是把类中含有@PostConstrunct和@PreDestroy注解的方法信息缓存到lifecycleMetadataCache中。也就是说在一个被spring管理的类中允许定义被这两个注解修饰的方法,那方法有那些要求那,看上面的new LifecycleElement这里,看LifecycleElement类
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());
}
看上面的异常,意思是不允许此类方法有方法参数,如果有参数则会抛异常。
三、使用场景
上面分析了InitDestroyAnnotationBeanPostProcessor类中postProcessMergedBeanDefinition方法的作用,就是把类中有@PostConstruct、@PreDestroy两个注解的方法信息进行缓存,至于这两个注解的作用及被这两个注解标记的方法何时调用后面会继续分析。
原创不易,有不正之处欢迎指正。
spring中BeanPostProcessor之三:InitDestroyAnnotationBeanPostProcessor(01)的更多相关文章
- spring中BeanPostProcessor之四:AutowiredAnnotationBeanPostProcessor(01)
在<spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)>中分析了CommonAnnotationBeanPos ...
- spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(01)
在spring中beanPostProcessor绝对是开天辟地的产物,给了程序员很多自主权,beanPostProcessor即常说的bean后置处理器. 一.概览 先来说下Instantiatio ...
- Spring中BeanPostProcessor
Spring中BeanPostProcessor 前言: 本文旨在介绍Spring动态配置数据源的方式,即对一个DataSource的配置诸如jdbcUrl,user,password,driverC ...
- spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)
在上篇博客中分享了InstantiationAwareBeanPostProcessor接口中的四个方法,分别对其进行了详细的介绍,在文末留下了一个问题,那就是postProcessPropertie ...
- spring(三):spring中BeanPostProcessor的使用
spring中实现BeanPostProcessor的后置处理器 ApplicationContextAwareProcessor 进入该实现类内部 可以看到:该类帮我们组建IOC容器,判断我们的be ...
- spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(03)
前面介绍了InstantiationAwareBeanPostProcessor后置处理器的postProcessBeforeInstantiation和postProcessAfterInstant ...
- spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(02)
在上篇博客中写道了bean后置处理器InstantiationAwareBeanPostProcessor,只介绍了其中一个方法的作用及用法,现在来看postProcessBeforeInstanti ...
- Spring中的BeanPostProcessor
一.何谓BeanProcessor BeanPostProcessor是SpringFramework里非常重要的核心接口之一,我先贴出一段源代码: /* * Copyright 2002-2015 ...
- Spring中的BeanPostProcessor详解
Spring中的BeanPostProcessor详解 概述 BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初 ...
随机推荐
- 渗透神器cobalt strike在数字杀软环境下的使用
当我们拿到cobalt strike的beacon权限时,使用它如何渗透目标内网.因为我看网上的文章都是在无杀软下写的,这难免有点脱离实战环境,本文主要测试CS的beacon在数字杀软环境下进行常规渗 ...
- Android项目目录结构模板以及简单说明
1) src 文件 编写java代码的文件目录,遵循java的命名规范.分包 2) gen 文件 包含了android的资源文件的标识符,是不需要程序员维护,是自动添加的 3) asse ...
- 第十周Java实验作业
实验十 泛型程序设计技术 实验时间 2018-11-1 1.实验目的与要求 (1) 理解泛型概念: 泛型:也称参数化类型,就是在定义类,接口和方法时,通过类型参数只是将要处理的类型对象.(如Arra ...
- 翻转-Flip Columns For Maximum Number of Equal Rows
2020-02-20 11:00:06 问题描述: 问题求解: 翻转题一个常见的思路就是站在结束的状态来反推最初的状态,本题的解题思路就是站在结束的时候的状态来进行反推. 如果在最终的状态i-row是 ...
- MySql InnoDB中的锁研究
# MySql InnoDB中的锁研究 ## 1.InnoDB中有哪些锁### 1. 共享和排他(独占)锁(Shared and Exclusive Locks) InnoDB实现标准的行级锁定,其中 ...
- 巴什博弈 HDU-1846
描述:一堆石子有 n 个 ,两个人开始轮流取,每人最多取m个,最少取1个,最后一个将石子取完的是赢家. 思路:对于先手来说,如果有(m+1)个石子,先手取 k 个,后手就可以取 m+1-k 个,所以有 ...
- 面试刷题30:SpringBean的生命周期?
spring是Java软件开发的事实标准. 我是李福春,我在准备面试,今天的问题是:springBean的生命周期是怎样的? 答:spring最基础的能力是IOC(依赖注入),AOP(面向切面编程), ...
- IntelliJ Idea 中文乱码问题
首先,Idea真的是一款很方便的开发工具,但是关于中文乱码这个问题我不得不吐槽,这个编码也弄得这么麻烦干嘛呀...下面就说一下怎么解决中文乱码问题: 1.首先是编辑器的乱码,这个很好解决,file-& ...
- 使用Azure Functions 在web 应用中启用自动更新(一)分析基于轮询的 Web 应用的限制
1,引言 上一篇介绍了使用使用 Visual Studio 开发 "Azure Functions" 函数,此篇介绍 “Azure Functions” 的测试以及直接从 Vist ...
- Light of future-冲刺Day 6
目录 1.SCRUM部分: 每个成员进度 SCRUM 会议的照片 签入记录 代码运行截图 用户浏览界面 订单详情界面 管理员浏览界面 新增后台界面 2.PM 报告: 时间表 燃尽图 任务总量变化曲线 ...