spring源码--第七个后置处理器的使用:初始化方法

spring源码:九大后置处理器 目的: spring在完成一个bean的初始化、实例化的过程中,会用到九个后置处理器;本文梳理出这九个后置处理器 九大后置处理器 spring在初始化的过程中,会在九个地方分别调用了五个后置处理的九个方法 第一次调用后置处理器org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation InstantiationAwareBeanPostProcessor --& 阅读详情

目的

spring提供了三种初始化方法:
1、@PostConstruct、@PreDestory
2、实现 InitializingBean DisposableBean 接口,并实现对应的afterPropertiesSet()和destroy()方法
3、设置init-method和destory-method
本文主要解析三个初始化和销毁方法的源码

只是有一个点需要注意:@PostConstruct、@PreDestory这两个注解是通过后置处理器完成处理的 --> org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization

其他两种方式,不是通过后置处理器完成的

源码

1、三种初始化方法的优先级从高到低;在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

优先级之所以是这样,和源码中对三种配置方式处理的优先级有关系

测试代码

public class UserService04 implements InitializingBean,DisposableBean {

    public UserService04() {
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("实现接口DisposableBean销毁");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("实现接口InitializingBean初始化");
    }

    public void init(){
        System.out.println("initMethod");
    }

    public void destroyConfig(){
        System.out.println("destroyMethod");
    }

    @PostConstruct
    public void testPost(){
        System.out.println("注解PostConstruct init");
    }

    @PreDestroy
    public void testDestroy(){
        System.out.println("注解PreDestroy 销毁");
    }
}


@Configuration
@ComponentScan("com.springsource.initmethod")
public class InitMethodConfig {
    @Bean(initMethod = "init",destroyMethod = "destroyConfig")
    public UserService04 testUserService04(){
        return new UserService04();
    }
}

2、初始化方法
初始化方法的代码位置是在

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

在该方法中,完成了bean的初始化方法回调和bean的动态代理对象生成,主要来看初始化回调方法

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
	wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
	invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
	throw new BeanCreationException(
			(mbd != null ? mbd.getResourceDescription() : null),
			beanName, "Invocation of init method failed", ex);
}

对于@PostConstruct和@PreDestroy这两个注解,是在applyBeanPostProcessorsBeforeInitialization()中完成处理的,而剩下两种初始化方法,是在invokeInitMethods()中完成的,所以,对于注解的方式,优先级最高

我们先来说invokeInitMethods()方法,也就是后两种初始化方法:

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
	//这里是处理实现了InitializingBean接口的初始化方法
	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 {
			// 调用实现类中的afterPropertiesSet()方法
			((InitializingBean) bean).afterPropertiesSet();
		}
	}
	//这里是来处理init-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);
		}
	}
}

可以看到,代码中是先判断当前bean是否是InitializingBean的实现类,然后优先调用了afterProperties();
然后再调用beanDefinition中对应的initMethod;需要说明的是:initMethod这种方式,对应的初始化方法和销毁方法,是在将bean添加到beanDefinitionMap中的时候,对bean进行了解析,获取到对应的initMethod和destroyMethod,然后放到了beanDefinition中

我们接着来说@PostConstruct和@PreDestroy注解的处理
该注解是由CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization和postProcessBeforeDestruction来处理的

@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	/**
	 * 在初始化bean的时候,会在这里处理注解的初始化方法 @PostConstruct
	 * 从cache中获取到当前bean的元对象
	 * 在invokeInitMethods方法中,就是
	 */
	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;
}

这是初始化方法对应的处理类,在此之前,在第三个后置处理器调用的时候,会调用到org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition;在该方法中,会找出当前bean中对应的@PostConstruct和@PreDestroy注解对应的方法,存入到lifecycleMetadataCache这个map中

然后在调用postProcessBeforeInitialization()方法的时候,注解从map中遍历所有的初始化方法,然后依次调用

3、销毁方法
三个销毁方法是在调用

@Override
public void destroy() {
	if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
		for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
			//这里是处理@PreDestroy注解对应的方法
			processor.postProcessBeforeDestruction(this.bean, this.beanName);
		}
	}

	if (this.invokeDisposableBean) {
		if (logger.isDebugEnabled()) {
			logger.debug("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接口的类
				((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);
			}
		}
	}

	if (this.destroyMethod != null) {
		//处理destroyMethod方法
		invokeCustomDestroyMethod(this.destroyMethod);
	}
	else if (this.destroyMethodName != null) {
		Method methodToCall = determineDestroyMethod(this.destroyMethodName);
		if (methodToCall != null) {
			invokeCustomDestroyMethod(methodToCall);
		}
	}
}

在这里插入图片描述
调用链是这样的,可以看到,在销毁bean的时候,也是按照文章开头的顺序来进行销毁的;而对应的原理和初始化方法调用的原理是一样的

spring源码 第二个后置处理器方法的使用-推断构造函数 spring一个bean初始化以及销毁的流程中,有九个后置处理器需要执行,这篇博客主要记录第二个后置处理器推断构造函数的后置处理器的源码逻辑 第一个后置处理器的调用 在第一个后置处理器被调用之前,会进行一系列的判断 会先调用第一个后置处理器,判断是否返回了bean,如果返回了bean,且不为null,就直接调用第八个后置处理器,完成bean的代理,然后return了之后,就结束了一个bean的生命周期,也即:一个bean就初始化完成了 第一个后置处理器是:org.springframework.beans. 阅读详情

相关推荐

spring源码:注册后置处理器

目的 程序员在对spring扩展的时候,可以自己实现后置处理器,完成特定的业务操作,该篇博客,主要是学习spring如何将程序员提供的后置处理器添加到spring容器中的; 顺带,将spring初始化流程中,其他几个方法做一个大致的解析和介绍 源码学习 registerBeanPostProcessors(beanFactory); 该方法是用来完成,注册BeanPostProcessor实现类的 如果我们自己实现了BeanPostProcessor接口,并提供了自己的业务处理逻辑,spring首先会把我们

小小少年的博客 501

@PostConstruct注解原理

@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。 Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。 通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序: Constru.

csdnlaiyanqi的博客 864

服务器centos上安装IC618(virtuoso)教程

只需要按照提供的步骤即可实现IC618安装。有需要详情请联系QQ:563962386

swicthsober的博客 1万+

Spring后置处理器源码,彻底理解Spring核心

简单对上篇做个总结: 首先咱们一起写了一个HelloWorld版本的Spring。因为Spring核心是控制反转,就是Bean对象都交给Spring来管理。开发者使用时只需要获取即可。在使用时分为两步:第一步,通过注解配置创建Spring上下文容器;第二步,从中获取需要的Bean来使用。 那讲道理就先把这两步需要的框架构造出来,于是先有了下面的架子: 然后咱们要把这个架子填充血肉,达到真的可以通过注解来使用Spring,进行依赖注入的目标。那首先要把使用到的注解定义出来: 根

Moonxiyue的博客 376

cocos2dx中DrawNode画线锯齿和非凸多边形填充

记录一下在cocos2dx中使用DrawNode所遇到的2个问题 1.画线锯齿问题 ios版本下,在AppController.mm中设置CCEAGLView的multiSampling和numberOfSamples。如下图 CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [window bounds]

hello-world 5414

MCGS触摸屏Modbus TCP通讯实战:从寄存器写入到字符串处理的完整代码解析

本文详细解析了MCGS触摸屏通过Modbus TCP协议实现寄存器写入和字符串处理的完整代码,涵盖单寄存器写入、多寄存器写入及字符串传输等核心技术。文章还提供了MCGS组态环境中的实战配置步骤和常见问题排查方法,帮助开发者快速掌握工业自动化通讯的关键技术。

study的专栏 755

SpringBoot源码解读与原理分析(十二)后置处理器

针对bean对象的后置处理器:BeanPostProcessor针对BeanDefinition的后置处理器:BeanDefinitionRegistryPostProcessor这两种都是针对IOC容器中的Bean,在其生命周期的某一阶段前后进行一些切入处理。BeanPostProcessor切入的时机是bean对象初始化阶段前、后。

挑灯日记 记录自己 1886

工业预测模型避坑指南:PHM2012轴承数据实战中,LSTM、CNN、Transformer到底怎么选?

本文深入探讨了工业预测模型在PHM2012轴承数据下的选型策略,对比了LSTM、CNN和Transformer等主流模型在轴承寿命预测任务中的表现。通过真实实验数据,提供了可复现的选型决策框架,帮助工程师根据数据规模、硬件条件和精度要求选择最佳模型。文章还揭示了工程落地中的隐藏陷阱,如数据不均衡和工况迁移挑战,并提出了解决方案。

weixin_33694172的博客 493

Spring源码系列-第2章-后置工厂处理器和Bean生命周期

*** @param bean the new bean instance 正在创建的bean的实例* @param beanName the name of the bean 该bean的名称返回的bean是包装过后的bean*/ /*** 这个方法是BeanPostProcessor接口中的一个方法,* 用于在bean初始化回调之前(如InitializingBean的afterPropertiesSet或自定义init-method),

xiejunxing的专栏 1066

无网络环境部署:手动获取并安装OneNote for Windows 10完整指南

本文提供了一份详尽的OneNote for Windows 10离线安装指南。针对无网络或内网隔离环境,详细介绍了如何从官方渠道获取正确的产品ID,利用第三方工具下载纯净的.appxbundle安装包,并解决系统兼容性与依赖框架问题。最后,通过PowerShell管理员命令完成安全部署,是IT管理员和高级用户在离线环境下部署UWP应用的实用参考。

loss4bartender的博客 496

【LDPC-7】LLR量化位宽对LDPC译码性能的影响分析——以最小和译码算法为例进行matlab仿真

最小和译码算法的步骤如下:最后译码结果如果满足或者完成所有迭代次数,则译码算法停止迭代,否则继续进行译码迭代操作。

FPGA/MATLAB学习教程/源码/项目合作开发 1471

Spring源码之BeanFactoryPostProcessor(后置处理器)

Spring源码之BeanFactoryPostProcessor(后置处理器)。 有点水平的Spring开发人员想必都知道BeanFactoryPostProcessor也就是常说的后置管理器,这是Spirng生命周期中的一个接口,实现这个接口可以在beanFactory初始化前做一些事。 我们熟知的Spring和Mybatis的结合,正是因为Mybatis实现了BeanFactoryPostProcessor,它的重要性不言而喻,深入理解他对于切入Mybatis源码有着深刻的意义。 如下图是简单的应用:

程序员田同学的博客 487

从0到1构建数据分析AI Agent:数据采集、洞察生成与报告自动化

在企业数字化转型的今天,数据分析师80%的时间被消耗在重复取数、数据清洗、报表排版等低价值劳动上,真正用于深度业务洞察和决策支持的时间不足20%。本文将从核心概念、技术原理、代码实现、落地实践全维度,教你从0到1搭建一套完整的数据分析AI Agent系统,实现「用户用自然语言提需求→Agent自动采集多源数据→AI自动挖掘业务洞察→自动生成符合业务要求的多格式报告」的全链路自动化,平均可将需求响应速度从天级压缩到分钟级,释放70%以上的分析师人力成本。

AI Python 编程之道的博客 472

聚焦Spring后置处理器分析对比

Spring Framework 中的后置处理器允许在容器实例化 Bean 或者在 Bean 的生命周期中进行操作。从源码上来看的话,其实其扩展机制下的后置处理器其实很多。我们重点放到我们常用的几个上BeanPostProcessor、BeanFactoryPostProcessor来聚焦分析一下。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 9万+

基于深度学习的生活垃圾检测与分类系统:YOLOv5、YOLOv6、YOLOv7与YOLOv8实现

本项目的目标是开发一个基于YOLO系列模型的生活垃圾检测与分类系统。数据集准备与标注:收集并标注生活垃圾图像数据集。模型训练:使用YOLOv5、YOLOv6、YOLOv7、YOLOv8等深度学习模型训练垃圾分类系统。UI界面设计:设计一个简洁的用户界面,支持图像或视频的上传与垃圾分类结果展示。实时垃圾检测与分类:通过摄像头进行实时垃圾检测和分类。结果展示与保存:展示检测结果,支持用户保存分类后的图像或视频。

YOLO 705

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

spring源码-第七个后置处理器的使用

初始化方法的处理 这个笔记中,记录的就是第七个后置处理器的使用,这篇笔记就简单做一个总结吧 在spring源码中,提供了三种初始化方法,spring也指定了三种初始化方法的优先级:@PostConstruct > InitializingBean接口 > init-method 在初始化方法被调用的时候,只有@PostConstruct是在第七个后置处理器被调用的,其实逻辑和@Autowired的思想是一样的,先找到加了注解的方法,然后执行 ...

小小少年的博客 232

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Spring源码解析(二):bean容器的创建、注册默认后置处理器、bean定义扫描类

}//创建注解容器,入参为配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config . class);//获取某个bean Book book = context . getBean(Book . class);//关闭容器 context . close();} }调用ClassPathBeanDefinitionScanner的有参构造方法。

从基础到源码解析的学习记录 1883

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【spring源码系列-02】通过refresh方法剖析IOC的整体流程

通过refresh方法剖析IOC的整体流程

zhenghuishengq的博客 1万+

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析

Spring有两种类型的后置处理器,分别是和,这里再贴出我画的 Spring 启动过程,可以看看这两种后置处理器在 Spring 启动过程中位置。总结一下执行顺序先执行了的方法,按照顺序Ordered> 其他;再执行了的方法;最后执行的方法,按照顺序Ordered> 其他;

dongdong199033的博客 1万+

Spring源码解析(八):bean后置处理器CommonAnnotationBeanPostProcessor

查找bean的@Resource属性和@PostConstruct和@PreDestroy方法并缓存起来@Resource注解属性填充初始化前执行解析@PostConstruct注解的初始化方法销毁前执行解析@PreDestroy主键的销毁方法。

从基础到源码解析的学习记录 1913

Spring 后置处理器源码

在《几种自定义Spring生命周期的初始化和销毁方法》最后一段描述了启动 Spring 容器过程中,初始化和销毁方法的执行时机,那么在 Spring 中是如何做到的呢? 注册主配置类 Spring 使用AnnotationConfigApplicationContext context = new AnnotationConf...

xiaoyaGrace的博客 357

Spring注解驱动开发第29讲——注册完AnnotationAwareAspectJAutoProxyCreator后置处理器之后,就得完成BeanFactory的初始化工作了

写在前面 经过前面的研究,我们发现,IOC容器在创建对象的时候,会注册这一些后置处理器,而在上一讲中,就已经把AnnotationAwareAspectJAutoProxyCreator这个后置处理器创建出来了,它呢,就是@EnableAspectJAutoProxy注解利用AspectJAutoProxyRegistrar给容器中创建出的一个bean的配置信息。 当然了,在注册后置处理器的时候,这个bean肯定就已经提前创建出来了。而且,它呢,我们也都知道是一个后置处理器,只要这个后置处理器已经创建出来并

李阿昀的博客 3246

Spring源码解析一:容器初始化

超详细Spring源码解析一:容器初始化 学习java也有几个月了,之前学习完Spring的源码一直没有时间总结(主要是懒),今天抽空回头做了一下复习,就想着将Spring源码的解析和理解分享出来,可能会有不贴切的地方还希望看客海涵指出。 前言 首先让我们看看当我们实例化一个容器时,spring做了什么 //这是我们常用的实例化方式 AnnotationConfigApplicationCon...

weixin_44130043的博客 367

[spring学习]5、bean的后置处理器(BeanPostProcessor)

在这篇文章中,将会介绍bean的后置处理器,由于这个涉及到AOP的思想,这里不进行过多的深入,也就是不讲原理(后面文章会手写源码),这里只介绍后置处理器如何使用。 在spring中,后置处理器会在bean初始化化之前和初始化之后进行调用,做相应的处理,我们可以在后置处理器中对bean进行统一的管理和操作 我们要使用后置处理器,首先需要实现BeanPoatProcessor这个接口,下面我们创建一个类来实现这个接口。 参数介绍使用 创建好之后要进行配置才能生效,这

秃头披风侠的博客 3218

6-spring源码阅读之invokeBeanFactoryPostProcessors方法

上一节已经说了postProcessBeanFactory空方法的扩展点使用,这一节开始正式进入比较重要的环节,那一节我们来聊一聊invokeBeanFactoryPostProcessors这个方法。

酸萝卜别吃 1760

Spring注解驱动开发——bean的后置处理器

BeanPostProcessor:是一个接口,bean的后置处理器(实际是在bean的初始化前后执行操作) public class MyBeanPostProcessor implements BeanPostProcessor{ /** * bean是容器调用构造器创建的实例 * beanName是实例的id * 在所有初始化方法之前调用 */ public Obj...

如不來的博客 2886
上一篇: spring源码:九大后置处理器
下一篇: spring源码:实例化bean的准备工作
小小少年_
博客等级 码龄10年 63粉丝 146原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值