Spring bean的生命周期和扩展

接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,以具体实例看bean生命周期的一些执行阶段

bean生命周期流程

生命周期扩展处理说明
实例化:createBeanInstance

构造方法, 如@Autowired的构造方法注入依赖bean

如UserService构造方法注入AppDAO:

@Autowired
public UserService(AppDAO appDAO) {
    System.out.println("@Autowired appDAO:" + appDAO);
    this.appDAO = appDAO;
}
属性设置:populateBean

如setter方法注入的依赖

如@Autoware的filed注入

如UserService中注入UserDAO:

@Resource(name = "u")
public void setUserDAO(UserDAO userDAO) {
    System.out.println("setUserDAO:" + userDAO);
    this.userDAO = userDAO;
}
初始化:initializeBean

1. BeanPostProcessor#postProcessBeforeInitialization

2. @PostConstruct

3. InitializingBean#afterPropertiesSet

initMethod

4. BeanPostProcessor#postProcessAfterInitialization

上一步骤属性设置完后,初始化方法前后都可以扩展。

例如BeanPostProcessor#postProcessBeforeInitialization,直接改变了set注入的appDAO对象

@Component
public class ServiceBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Bean 初始化前的逻辑
        if (beanName.equals("userService")) {
            UserService userService = (UserService)bean;
            AppDAO appDAO = new AppDAOImpl2();
            userService.setAppDAO(appDAO);
            System.out.println("postProcessBeforeInitialization:" + ":" + bean);
        }
        return bean;
    }
销毁

1. @PreDestroy

2. DisposableBean#destroy

destroyMethod

附org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

/**
	 * Actually create the specified bean. Pre-creation processing has already happened
	 * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
	 * <p>Differentiates between default bean instantiation, use of a
	 * factory method, and autowiring a constructor.
	 * @param beanName the name of the bean
	 * @param mbd the merged bean definition for the bean
	 * @param args explicit arguments to use for constructor or factory method invocation
	 * @return a new instance of the bean
	 * @throws BeanCreationException if the bean could not be created
	 * @see #instantiateBean
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 */
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

扩展执行

接上文:AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,来看这些BeanPostProcessor如何起作用

测试bean定义类如下

@Service("userService")
public class UserService implements InitializingBean, DisposableBean {

    private String userServiceName;

    private UserDAO userDAO;
    private AppDAO appDAO;

    /**
     * field 注入
     */
    @Autowired
    private CommonService commonService;

    public UserService() {
        System.out.println("constructor");
    }

    /**
     * 类似于 InitializingBean 的 afterPropertiesSet() 方法
     */
    @PostConstruct
    public void init() {
        System.out.println("PostConstruct userService");
        System.out.println("userDAO is not null:" + (userDAO != null));
        System.out.println("appDAO is not null:" + (appDAO != null));
        userServiceName = "selfUserService";
    }

    /**
     * setter注入
     * @param userDAO
     */
    @Resource(name = "u")
    public void setUserDAO(UserDAO userDAO) {
        System.out.println("setUserDAO:" + userDAO);
        this.userDAO = userDAO;
    }

    /**
     * 构造器注入
     * @param appDAO
     */
    @Autowired
    public UserService(AppDAO appDAO) {
        System.out.println("@Autowired appDAO:" + appDAO);
        this.appDAO = appDAO;
    }

    public void add(User user) {
        userDAO.save(user);
    }

    public UserDAO getUserDAO() {
        return userDAO;
    }

    /**
     * 类似于 DisposableBean 的 destroy() 方法
     */
    @PreDestroy
    public void preDestroy() {
        System.out.println("preDestroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet userService");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("destroy userService");

    }

    public void setUserServiceName(String userServiceName) {
        this.userServiceName = userServiceName;
    }

    public void setAppDAO(AppDAO appDAO) {
        this.appDAO = appDAO;
    }

    @Override
    public String toString() {
        return "UserService{" +
                "userServiceName='" + userServiceName + '\'' +
                ", userDAO=" + userDAO +
                ", appDAO=" + appDAO +
                ", commonService=" + commonService +
                '}';
    }
}

InstantiationAwareBeanPostProcessors:SmartInstantiationAwareBeanPostProcessor

推断构造函数,最后是AutowiredAnnotationBeanPostProcessor完成构造函数的推断

最后判断有@Autowired的构造函数 完成实例化过程

InstantiationAwareBeanPostProcessor:CommonAnnotationBeanPostProcessor

populate阶段CommonAnnotationBeanPostProcessor完成setter注入

/**
 * setter注入
 * @param userDAO
 */
@Resource(name = "u")
public void setUserDAO(UserDAO userDAO) {
    System.out.println("setUserDAO:" + userDAO);
    this.userDAO = userDAO;
}

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties

@Override
	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;
	}

InstantiationAwareBeanPostProcessor:AutowiredAnnotationBeanPostProcessor

populate阶段AutowiredAnnotationBeanPostProcessor完成@Autorwired的filed的注入,具体可以再次阅读:Spring5.1.3 @Autorwired注解原理重新回顾-CSDN博客

BeanPostProcessor#postProcessBeforeInitialization

initializeBean阶段会执行BeanPostProcessor的postProcessBeforeInitialization方法
执行自定义的BeanPostProcessor

执行CommonAnnotationBeanPostProcessor解析@PostConstruct注解

@PostConstruct
public void init() {
    System.out.println("PostConstruct userService");
    System.out.println("userDAO is not null:" + (userDAO != null));
    System.out.println("appDAO is not null:" + (appDAO != null));
    userServiceName = "selfUserService";
}

执行InitializingBean的afterPropertiesSet方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		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();
			}
		}

		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);
			}
		}
	}
BeanPostProcessor#postProcessAfterInitialization

InitializingBean最后阶段会执行BeanPostProcessor的postProcessAfterInitialization方法

本例

@Component
public class ServiceBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Bean 初始化前的逻辑
        if (beanName.equals("userService")) {
            UserService userService = (UserService)bean;
            AppDAO appDAO = new AppDAOImpl2();
            userService.setAppDAO(appDAO);
            System.out.println("postProcessBeforeInitialization:" + ":" + bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // Bean 初始化后的逻辑
        if (beanName.equals("userService")) {
            System.out.println("postProcessAfterInitialization:" + ":" + bean);
        }
        return bean;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/953596.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【再谈设计模式】模板方法模式 - 算法骨架的构建者

一、引言 在软件工程、软件开发过程中&#xff0c;我们经常会遇到一些算法或者业务逻辑具有固定的流程步骤&#xff0c;但其中个别步骤的实现可能会因具体情况而有所不同的情况。模板方法设计模式&#xff08;Template Method Design Pattern&#xff09;就为解决这类问题提供了…

01 Oracle自学环境搭建(Windows系统)

1 Oracle12C安装 1.1 下载 官网地址&#xff1a;https://www.oracle.com/ 进入官网→Resource→Customer Downloads 如果没有登录&#xff0c;会提示登录后后才能下载 选择适合自己的版本&#xff08;我电脑是Windows系统 64位&#xff09; 选择需要的安装包进行下载 双击下载…

java语法知识(二)

1. class文件可以直接拖动到idea中&#xff0c;显示源码。 2.idea快捷键&#xff1a; sout : System.out.println 输出内容.sout :---》 System.out.println(输出内容); psvm: public static void main() 格式化&#xff1a;ctrl altL 复制粘贴&#xff1a;ctrld 3.注释…

macos python环境安装

安装的问题 mac 安装 python brew install python 通过brew安装的python安装路径 打开终端&#xff0c;输入brew search python&#xff1a; 为啥会被安装在这里 Frameworks 的用途&#xff1a;/Library/Frameworks 是 macOS 系统中专门用于存放框架的目录。框架是一种结构…

计算机网络 笔记 数据链路层 2

1,信道划分&#xff1a; (1)时分复用TDM 将时间等分为“TDM帧”&#xff0c;每个TDM帧内部等分为m个时隙&#xff0c;m个用户对应m个时隙 缺点&#xff1a;每个节点只分到了总带宽的1/m,如果有部分的1节点不发出数据&#xff0c;那么就会在这个时间信道被闲置&#xff0c;利用…

ElasticSearch在Windows环境搭建测试

引子 也持续关注大数据相关内容一段时间&#xff0c;大数据内容很多。想了下还是从目前项目需求侧出发&#xff0c;进行相关学习。Elasticsearch&#xff08;ES&#xff09;是位于 Elastic Stack&#xff08;ELK stack&#xff09; 核心的分布式搜索和分析引擎。Logstash 和 B…

计算机网络 笔记 网络层1

网络层功能概述 主要的任务是把分组从源端传输到目的端&#xff0c;为分组交换网上的不同主句提供通信服务&#xff0c;网络层的传输单位是数据报。 主要的功能&#xff1b; 1&#xff0c;路由选择&#xff1a;路由选择指网络层根据特定算法&#xff0c;为数据包从源节点到目…

Rubyer-WPF:打造优雅、精致的 WPF 用户界面

在桌面应用开发领域&#xff0c;WPF&#xff08;Windows Presentation Foundation&#xff09;凭借其强大的 UI 设计能力和丰富的功能&#xff0c;始终是开发者们青睐的工具之一。今天&#xff0c;我将为大家介绍一款专注于 WPF UI 设计的优秀项目——Rubyer-WPF&#xff0c;它…

设计模式 行为型 访问者模式(Visitor Pattern)与 常见技术框架应用 解析

访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为设计模式&#xff0c;它允许你在不改变元素类的前提下定义作用于这些元素的新操作。这种模式将算法与对象结构分离&#xff0c;使得可以独立地变化那些保存在复杂对象结构中的元素的操作。 假设我们有一个复杂的对…

继承多态语法糖

抽象类(通用) 子类继承父类方法后&#xff0c;这个子类对象如果执行方法的话&#xff0c;只要子类重写了就执行子类的&#xff0c;不执行父类的。 /*** 功能&#xff1a;* 作者&#xff1a;IT伟* 日期&#xff1a;2025/1/13 19:20*/ // 抽象类 A abstract class A {// 构造函…

MarS:一个由生成基础模型驱动的金融市场模拟引擎

“MARS: A FINANCIAL MARKET SIMULATION ENGINE POWERED BY GENERATIVE FOUNDATION MODEL” 项目主页&#xff1a;https://mars-lmm.github.io/ 论文地址&#xff1a;https://arxiv.org/pdf/2409.07486 Github地址&#xff1a;https://github.com/microsoft/MarS/ 摘要 生成…

macOS 使用 FreeRDP 远程访问 Windows:完整指南20250109

&#x1f5a5;️ macOS 使用 FreeRDP 远程访问 Windows&#xff1a;完整指南 引言 随着远程办公需求的快速增长&#xff0c;跨平台远程管理已经成为不可或缺的技能之一。作为一款开源轻量的远程桌面协议实现工具&#xff0c;FreeRDP 为 macOS 用户提供了一个简单、高效的解决…

两分钟解决 :![rejected] master -> master (fetch first) , 无法正常push到远端库

目录 分析问题的原因解决 分析问题的原因 在git push的时候莫名遇到这种情况 若你在git上修改了如README.md的文件。由于本地是没有README.md文件的&#xff0c;所以导致 远端仓库git和本地不同步。 将远端、本地进行合并就可以很好的解决这个问题 注意&#xff1a;直接git pu…

计算机图形学【绘制立方体和正六边形】

工具介绍 OpenGL&#xff1a;一个跨语言的图形API&#xff0c;用于渲染2D和3D图形。它提供了绘制图形所需的底层功能。 GLUT&#xff1a;OpenGL的一个工具库&#xff0c;简化了窗口创建、输入处理和其他与图形环境相关的任务。 使用的函数 1. glClear(GL_COLOR_BUFFER_BIT |…

springboot高校教室资源管理平台

Spring Boot高校教室资源管理平台是一个基于Spring Boot框架开发的高校教室资源管理系统。 一、平台背景与意义 随着高校规模的不断扩大&#xff0c;教室资源的管理变得日益复杂。传统的管理方式往往依赖于人工记录和纸质文件&#xff0c;不仅效率低下&#xff0c;而且容易出…

[笔记] 使用 Jenkins 实现 CI/CD :从 GitLab 拉取 Java 项目并部署至 Windows Server

随着软件开发节奏的加快&#xff0c;持续集成&#xff08;CI&#xff09;和持续部署&#xff08;CD&#xff09;已经成为确保软件质量和加速产品发布的不可或缺的部分。Jenkins作为一款广泛使用的开源自动化服务器&#xff0c;为开发者提供了一个强大的平台来实施这些实践。然而…

正点原子STM32F103战舰版电容触摸键学习

一、tpad.h代码 #ifndef __TPAD_H #define __TPAD_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/ /* TPAD 引脚 及 定时器 定义 *//* 我们使用定时器的输入捕获功能, 对TPAD进行检…

JVM:ZGC详解(染色指针,内存管理,算法流程,分代ZGC)

1&#xff0c;ZGC&#xff08;JDK21之前&#xff09; ZGC 的核心是一个并发垃圾收集器&#xff0c;所有繁重的工作都在Java 线程继续执行的同时完成。这极大地降低了垃圾收集对应用程序响应时间的影响。 ZGC为了支持太字节&#xff08;TB&#xff09;级内存&#xff0c;设计了基…

zerox - 使用视觉模型将 PDF 转换为 Markdown

7900 Stars 478 Forks 39 Issues 17 贡献者 MIT License Python 语言 代码: https://github.com/getomni-ai/zerox 主页: OmniAI. Automate document workflows 更多AI开源软件&#xff1a;AI开源 - 小众AI zerox基于视觉模型 API 服务&#xff0c;提供了将 PDF 文档转化为 Mar…

JAVA:Spring Boot 集成 JWT 实现身份验证的技术指南

1、简述 在现代Web开发中&#xff0c;安全性尤为重要。为了确保用户的身份&#xff0c;JSON Web Token&#xff08;JWT&#xff09;作为一种轻量级且无状态的身份验证方案&#xff0c;广泛应用于微服务和分布式系统中。本篇博客将讲解如何在Spring Boot 中集成JWT实现身份验证…