Spring源码学习(六)-spring初始化回调方法源码学习
Multiple lifecycle mechanisms configured for the same bean, with
different initialization methods, are called as follows:
Methods annotated with @PostConstruct
afterPropertiesSet() as defined by the InitializingBean callback interface
A custom configured init() method
Destroy methods are called in the same order:
Methods annotated with @PreDestroy
destroy() as defined by the DisposableBean callback interface
A custom configured destroy() method
2.三种配置初始化bean的方式,调用时机不同,对于注解,是在spring生命周期中第七个bean后置处理器调用的时候,由CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization()方法来处理
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//如果目标类中的方法,添加了@PostConstruct注解,就添加到currInitMethods
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);
}
}
//如果目标类的方法,添加了@PreDestory注解,就添加到currDestroyMethod中
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);
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) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
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()) {
boolean debug = logger.isDebugEnabled();
for (LifecycleElement element : initMethodsToIterate) {
if (debug) {
logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
element.invoke(target);
}
}
}
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable { //判断当前bean是否是 InitializingBean接口的实现类,如果是,判断是否实现了 afterPropertiesSet() 方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
} //如果是在@Bean中配置了init-method和destroy-method,那执行的是这里的方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
public void destroy() {
//这里是处理@PreDestroy注解的销毁方法
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
//这里是处理 DisposableBean 接口实现类中destroy()销毁方法的逻辑
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
//这是处理@Bean中 destory-method这种方式的销毁方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
Spring源码学习(六)-spring初始化回调方法源码学习的更多相关文章
- Spring学习(六)-----Spring使用@Autowired注解自动装配
Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...
- spring cloud学习(六)Spring Cloud Config
Spring Cloud Config 参考个人项目 参考个人项目 : (希望大家能给个star~) https://github.com/FunriLy/springcloud-study/tree ...
- Hystrix微服务容错处理及回调方法源码分析
前言 在 SpringCloud 微服务项目中,我们有了 Eureka 做服务的注册中心,进行服务的注册于发现和服务治理.使得我们可以摒弃硬编码式的 ip:端口 + 映射路径 来发送请求.我们有了 F ...
- Spring注解驱动开发(六)-----spring容器创建【源码】
Spring容器的refresh()[创建刷新] 1.prepareRefresh()刷新前的预处理 1).initPropertySources()初始化一些属性设置;子类自定义个性化的属性设置方法 ...
- spring学习 六 spring与mybatis整合
在mybatis学习中有两种配置文件 :全局配置文件,映射配置文件.mybatis和spring整合,其实就是把mybatis中的全局配置文件的配置内容都变成一个spring容器的一个bean,让sp ...
- spring boot 学习(六)spring boot 各版本中使用 log4j2 记录日志
spring boot 各版本中使用 log4j2 记录日志 前言 Spring Boot中默认日志工具是 logback,只不过我不太喜欢 logback.为了更好支持 spring boot 框架 ...
- Spring Cloud 学习 (六) Spring Cloud Config
在实际开发过程中,每个服务都有大量的配置文件,例如数据库的配置.日志输出级别的配置等,而往往这些配置在不同的环境中也是不一样的.随着服务数量的增加,配置文件的管理也是一件非常复杂的事 在微服务架构中, ...
- Spring boot 学习六 spring 继承 mybatis (基于注解)
MyBatis提供了多个注解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,这些都是建立动态语言和让MyBatis执 ...
- Bean 注解(Annotation)配置(2)- Bean作用域与生命周期回调方法配置
Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...
随机推荐
- 19、State 状态模式
“人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换.就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流 ...
- Vue中v-model指令的常用修饰符
v-model指令有三个可以选用的修饰符:.lazy..number以及.trim.vue官方对此的描述为: .number-输入字符串转为有效的数字 .lazy-取代input监听change事件 ...
- [转]解决The requested resource is not available的方法
此博文为转载博文,首先感谢原作者 HTTP Status 404(The requested resource is not available)异常主要是路径错误或拼写错误造成的,请按以下步骤逐一排 ...
- 强化学习 3—— 使用蒙特卡洛采样法(MC)解决无模型预测与控制问题
一.问题引入 回顾上篇强化学习 2 -- 用动态规划求解 MDP我们使用策略迭代和价值迭代来求解MDP问题 1.策略迭代过程: 1.评估价值 (Evaluate) \[v_{i}(s) = \sum_ ...
- C++游戏(大型PC端枪战游戏)服务器架构
实习期间深入参与到某大型pc端枪战游戏的后端开发中,此游戏由著名游戏工作室编写,代码可读性极高,自由时间对游戏后台代码进行了深入研究,在满足自身工作需要的同时对游戏后台的架构也有了理解,记录在此,以便 ...
- NodeJs path.resolve的使用
__dirname __dirname 指向运行代码的文件夹 console.info('__dirname', __dirname) // C:\Leslie\Web_learning\Daily- ...
- JavaScript Babel说明
babel插件只是去唤醒 @babel/core中的转换过程 转换模块需要手动安装 npm install @babel/core 转换方式需要安装 @babel/preset-env babel默认 ...
- angular中阿里矢量图标使用
<!DOCTYPE html> <html lang="en" ng-app="app"> <head> <meta ...
- [Kong 与 Konga与postgres数据库] 之 Kuberneres 部署
1.Kong的概述 Kong是一个clould-native.快速的.可扩展的.分布式的微服务抽象层(也称为API网关.API中间件或在某些情况下称为服务网格)框架.Kong作为开源项目在2015年推 ...
- linux手动安装python
前提:你的linux服务器必须有gcc编译器,gcc查看方法:linux命令行>gcc -v 如果返回版本信息证明已经安装, 如果找不到命令,跳到这篇手动安装gcc >>> l ...