SpringBoot日常:Spring扩展接口之InitializingBean

2024-08-29 16:20

本文主要是介绍SpringBoot日常:Spring扩展接口之InitializingBean,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 简介
    • 源码分析
    • 应用场景
    • 代码示例
    • 运行示例

简介

这篇文章主要介绍了Spring中InitializingBean的使用详细解析,InitializingBean是Spring提供的拓展性接口,提供了属性初始化后的处理方法,它只有一个afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。

源码分析

我们大概看一下初始化涉及的源码部分,主要为这两个方法,
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean#invokeInitMethods

/*** @return the initialized bean instance (potentially wrapped)* @see BeanNameAware* @see BeanClassLoaderAware* @see BeanFactoryAware* @see #applyBeanPostProcessorsBeforeInitialization* @see #invokeInitMethods* @see #applyBeanPostProcessorsAfterInitialization*/protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {//执行BeanPostProcessor接口实现类的postProcessBeforeInitialization方法wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//如果bean实现了InitializingBean或者自定义了initMethod,//会在这里执行InitializingBean#afterPropertiesSet和initMethod方法invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {//执行BeanPostProcessor接口实现类的postProcessAfterInitialization方法wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
	protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {//判断bean是否实现了InitializingBeanboolean isInitializingBean = (bean instanceof InitializingBean);if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("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,真接调用afterPropertiesSet(),((InitializingBean) bean).afterPropertiesSet();}}if (mbd != null && bean.getClass() != NullBean.class) {//获取bean自定义的init-method方法String initMethodName = mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) &&!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {//如果自定义了init-method方法,在这里开始执行;invokeCustomInitMethod(beanName, bean, mbd);}}}

看完源码部分,我们可以很清楚地知道InitializingBean#afterPropertiesSet方法和init-method是什么时候用什么方式来调用的( 通过反射调用init-method),且InitializingBean#afterPropertiesSet方法的执行时机要稍早于init-method。另外,如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法

应用场景

这个扩展点是比较有用的一个扩展点,可以用于

  • 修改默认设置的属性
  • 添加补充额外的属性值
  • 或者针对关键属性做校验
  • spring MVC内容有一个经典的实现场景,RequestMappingHandlerMapping完成URL与controller的映射工作
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {@Overridepublic void afterPropertiesSet() {initHandlerMethods();}	protected void initHandlerMethods() {//循环所有的beanfor (String beanName : getCandidateBeanNames()) {//如果bean名字不是以scopedTarget.开头if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {processCandidateBean(beanName);}}//日志输出handlerMethodsInitialized(getHandlerMethods());}protected void processCandidateBean(String beanName) {Class<?> beanType = null;try {beanType = obtainApplicationContext().getType(beanName);}catch (Throwable ex) {if (logger.isTraceEnabled()) {logger.trace("Could not resolve type for bean '" + beanName + "'", ex);}}//他们是否是Handler(类上标注@Controller注解或者@RequestMapping注解)if (beanType != null && isHandler(beanType)) {//获取这个类上所有标注@RequestMapping的方法信息,以RequestMappingInfo形式把他们储存到MappingRegistry中detectHandlerMethods(beanName);}}

代码示例

完成一个rsa对象的初始化,方便该类方法调用使用

@Slf4j
@Configuration
public class ExtendInitializingBean implements InitializingBean {private RSA rsa;@Overridepublic void afterPropertiesSet() {String priv = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJzDhvCJBIIuZzNu\n" +"+dHWY5inSAN6d/yqWOTl/5rWofT2+m59qjKoFuJ9kkuYUCkIpoEtLhu5PfOAdR9R\n" +"bsVnfXThgwOQFHx1/v4URXwOBrBHRYhPy8fApJSfdBWgKMs9GZ5WbDWVkPm7xhvJ\n" +"t716Wtx/leCjvq87jWVg8oo83uKtAgMBAAECgYAW77bNInG3QxHUy9kf03XpY8Rc\n" +"xJeiBMyShSJjuyFMMFy45jMM9rIOe8qiu+DdTXI14UXnRtsNHHpGgEmBoYrl4IZ9\n" +"Wgbxn0fkrcHaw4F8GoAapyqAgNkyU3kAf8of6G+ZeMulcZtbb7NXVkwTaRHOkzBg\n" +"2a44HCSQ2n/fHPxfwwJBANFhUKWMOV3SqEN7RjsxWNAk8P25xHzIWq6KCyhOx5Vm\n" +"KLIttnYUiA3UA3q5RJK8Hqh0a2JGcg8O9HawOuMWAAsCQQC/qxNG08pX8dm5mh5B\n" +"9d/Wc09U9V7Xni9gqqS5adjxChm97t5h8k3wRxTqDWHCJyZTkezy7pmZvaFWqwLO\n" +"xkMnAkBLEbIBeNIEkoejkiovBNVL40LIJXeOKaNhmrq/W+dw6CzFHWCi21+gXZhV\n" +"wuEUHwB68yqhFJLGVV1OxIaIbpXbAkBBY0WiRiKjuhiDHzbvXchNSu1nmIYQnSCg\n" +"o9aqgpfGM6HwkAtB8v3v2PAjoQkWyXBj1ka14fx43J6sCI9ep3jFAkBDi3wnlIzc\n" +"LpJxumw84P8f3pVJ1xKx9tchAh1W+hhcaq+/S+u3rIJcXfXWLojUp7yMyKjzy2lU\n" +"PNC8Qke0R/qC";String pub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcw4bwiQSCLmczbvnR1mOYp0gD\n" +"enf8qljk5f+a1qH09vpufaoyqBbifZJLmFApCKaBLS4buT3zgHUfUW7FZ3104YMD\n" +"kBR8df7+FEV8DgawR0WIT8vHwKSUn3QVoCjLPRmeVmw1lZD5u8Ybybe9elrcf5Xg\n" +"o76vO41lYPKKPN7irQIDAQAB";rsa = new RSA(priv, pub);log.info("afterPropertiesSet--Extend--run");}}

运行示例

在这里插入图片描述

这篇关于SpringBoot日常:Spring扩展接口之InitializingBean的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1118356

相关文章

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项