Spring扩展点系列-ApplicationContextAwareProcessor

news2024/11/15 6:46:20

文章目录

    • 简介
    • 源码分析
    • 示例代码
      • 示例一:扩展点的执行顺序
        • 运行示例一
      • 示例二:获取配置文件值
        • 配置文件application.properties内容
        • 定义工具类ConfigUtil
        • controller测试调用
        • 运行示例二
      • 示例三:实现ResourceLoaderAware读取文件
        • ExtendResourceLoaderAware 文件内容
        • token.json 文件
        • controller测试代码
        • 运行示例三

简介

spring容器中Bean的生命周期内所有可扩展的点的调用顺序
扩展接口 实现接口
ApplicationContextlnitializer initialize
AbstractApplicationContext refreshe
BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry
BeanDefinitionRegistryPostProcessor postProcessBeanFactory
BeanFactoryPostProcessor postProcessBeanFactory
instantiationAwareBeanPostProcessor postProcessBeforelnstantiation
SmartlnstantiationAwareBeanPostProcessor determineCandidateConstructors
MergedBeanDefinitionPostProcessor postProcessMergedBeanDefinition
InstantiationAwareBeanPostProcessor postProcessAfterlnstantiation
SmartInstantiationAwareBeanPostProcessor getEarlyBeanReference
BeanFactoryAware postProcessPropertyValues
ApplicationContextAwareProcessor invokeAwarelnterfaces
BeanNameAware setBeanName
InstantiationAwareBeanPostProcessor postProcessBeforelnstantiation
@PostConstruct
InitializingBean afterPropertiesSet
FactoryBean getobject
SmartlnitializingSingleton afterSingletonslnstantiated
CommandLineRunner run
DisposableBeandestroy
今天要介绍的是ApplicationContextAwareProcessor ,ApplicationContextAwareProcessor 本身是没有扩展点的,但其内部却有7个扩展点可供实现 ,分别为
  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ApplicationStartupAware
  • ApplicationContextAware

这些内部扩展点触发的时机在bean实例化之后,初始化之前。

1、EnvironmentAware:凡注册到Spring容器内的bean,实现了EnvironmentAware接口重写setEnvironment方法后,在工程启动时可以获得application.properties的配置文件配置的属性值。
2、EmbeddedValueResolverAware:用于获取StringValueResolver的一个扩展类, StringValueResolver用于获取基于String类型的properties的变量
3、ResourceLoaderAware:用于获取ResourceLoader的一个扩展类,ResourceLoader可以用于获取classpath内所有的资源对象,可以扩展此类来拿到ResourceLoader对象。
4、ApplicationEventPublisherAware:用于获取ApplicationEventPublisher的一个扩展类,ApplicationEventPublisher可以用来发布事件,结合ApplicationListener来共同使用
5、MessageSourceAware:用于获取MessageSource的一个扩展类,MessageSource主要用来做国际化
6、ApplicationStartupAware:要开始收集定制的StartupStep,组件可以实现ApplicationStartupAware接口直接获得ApplicationStartup实例或者在注入点请求ApplicationStartup类型。
7、ApplicationContextAware:可以用来获取ApplicationContext的一个扩展类,也就是spring上下文管理器,可以手动的获取任何在spring上下文注册的bean

源码分析

从下列源码的invokeAwareInterfaces方法可知,ApplicationContextAwareProcessor关联了大部分Spring内置Aware接口,它们的执行顺序如
下源码码所示从上到下,最开始是EnvironmentAware,最后是ApplicationContextAware

package org.springframework.context.support;

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;

	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}

	@Override
	@Nullable
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
				bean instanceof ApplicationStartupAware)) {
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationStartupAware) {
			((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}
}

示例代码

示例一:扩展点的执行顺序

示例一展示的是7个内部扩展点所执行的顺序

@Slf4j
@Configuration
public class ExtendInvokeAware implements EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware,
        ApplicationEventPublisherAware, MessageSourceAware, ApplicationStartupAware, ApplicationContextAware, BeanNameAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("setApplicationContext--Extend--run {}",applicationContext);
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        log.info("setApplicationEventPublisher--Extend--run {}",applicationEventPublisher);
    }

    @Override
    public void setApplicationStartup(ApplicationStartup applicationStartup) {
        log.info("setApplicationStartup--Extend--run {}",applicationStartup);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        log.info("setEmbeddedValueResolver--Extend--run {}",resolver);
    }

    @Override
    public void setEnvironment(Environment environment) {
        log.info("setEnvironment--Extend--run {}",environment);
    }

    @Override
    public void setMessageSource(MessageSource messageSource) {
        log.info("setMessageSource--Extend--run {}",messageSource);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        log.info("setResourceLoader--Extend--run {}",resourceLoader);
    }

    @Override
    public void setBeanName(String name) {
        log.info("setBeanName--Extend--run {}",name);
    }
}
运行示例一

在这里插入图片描述

示例二:获取配置文件值

展示如何利用实现EmbeddedValueResolverAware来获取配置文件的属性值

配置文件application.properties内容
db.user=navicat
db.password=navicat
db.driverClass=com.mysql.jdbc.Driver
定义工具类ConfigUtil

该工具类功能为传入的key获取对应value

@Component
public class ConfigUtil implements EmbeddedValueResolverAware {

    private StringValueResolver resolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
    }

    /**
     * 获取属性,直接传入属性名称即可
     * @param key
     * @return
     */
    public String getPropertiesValue(String key) {
        StringBuilder name = new StringBuilder("${").append(key).append("}");
        return resolver.resolveStringValue(name.toString());
    }

}
controller测试调用
@GetMapping("/testConfig")
public void testConfig() {
    String s = configUtil.getPropertiesValue("db.user");
    System.out.println(s);
}
运行示例二

在这里插入图片描述

示例三:实现ResourceLoaderAware读取文件

ExtendResourceLoaderAware 文件内容

实现ResourceLoaderAware 接口,并读取文件内容进行打印

@Slf4j
@Configuration
public class ExtendResourceLoaderAware implements ResourceLoaderAware {

    private ResourceLoader resourceLoader;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
        log.info("ApplicationContextAware--Extend--run {}",resourceLoader);
    }


    public void showResourceData() throws IOException
    {
        //This line will be changed for all versions of other examples
        Resource banner = resourceLoader.getResource("file:d:/token.json");

        InputStream in = banner.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(in));

        while (true) {
            String line = reader.readLine();
            if (line == null)
                break;
            System.out.println(line);
        }
        reader.close();
    }
}
token.json 文件
{"name":"张三"}
controller测试代码
@Autowired
ApplicationContext context;

@SuppressWarnings("resource")
@GetMapping("/testResource")
public void testResource() throws Exception{
    ExtendResourceLoaderAware extendResourceLoaderAware = (ExtendResourceLoaderAware) context.getBean("extendResourceLoaderAware");

    extendResourceLoaderAware.showResourceData();
}
运行示例三

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CleanClip - 「CleanClip」是一款专为 Mac 设计的桌面剪贴板工具

官方介绍 欢迎使用 CleanClip —— Mac 上最简洁高效的剪贴板管理工具。CleanClip 专为追求简约操作体验的用户设计&#xff0c;它帮助用户记录系统剪贴板上的内容&#xff0c;并提供强大的分类管理能力&#xff0c;帮助你整理复制的内容&#xff0c;提高办公效率。 智能简洁&…

MAVEN如何导入项目

工作中经常需要导入他人的项目&#xff0c;那么如何导入呢&#xff1f; 1&#xff0c; 选择Maven面板&#xff0c;点 2&#xff0c;选中对应项目的pom.xml&#xff0c;双击即可 3&#xff0c;如果没有maven面板&#xff0c;可以选择view->Appearnce->Tool Window Bars…

HTML5元素定位

1.元素定位 为了实现网页整体布局&#xff0c;我们先要知道&#xff0c;一个元素&#xff0c;是如何定位到页面上的某个位置的&#xff0c;这就是元素定位。 元素定位有四种&#xff0c;可以使用position样式来设置元素定位&#xff0c;所以此属性值有四种&#xff1a; stat…

MybatisPlus新增数据时怎么返回新增数据的id

问&#xff1a;MybatisPlus新增数据时怎么返回新增数据的id&#xff1f;答&#xff1a;当插入操作执行后&#xff0c;MyBatis Plus会自动获取生成的ID并将其设置到传入的实体类对象的id属性中。当然&#xff0c;这需要你的表字段ID是自增的 实体类代码 public class Sites {p…

东风德纳携手纷享销客打造汽车零部件行业营销数智化新标杆

为进一步提升数字化经营管理水平&#xff0c;加速数字化转型&#xff0c;推进“品牌向上”战略落实落地&#xff0c;9月2日&#xff0c;东风德纳车桥有限公司召开CRM项目启动会&#xff0c;携手纷享销客&#xff0c;打造汽车零部件行业营销数智化标杆工程。东风德纳车桥总经理陆…

高效Flutter应用开发:GetX状态管理实战技巧

探索GetX状态管理的使用 前言 在之前的文章中&#xff0c;我们详细介绍了 Flutter 应用中的状态管理&#xff0c;setState、Provider库以及Bloc的使用。 本篇我们继续介绍另一个实现状态管理的方式&#xff1a;GetX。 一、GetX状态管理 基础介绍 GetX 是一个在 Flutter 中…

【原创】【总结】【C++类的设计要点】一道十分典型的含继承与虚函数的类设计题

设计类时的要点 1构造函数与析构函数&#xff1a;先在public中写上构造函数与析构函数 2成员函数&#xff1a;根据题目要求在public中声明成员函数&#xff1b;成员函数的实现在类内类外均可&#xff0c;注意若在类外实现时用::符号表明是哪个类的函数 3数据成员&#xff1a;关…

STM32L051K8U6-HAL-串口中断控制灯闪烁速度

HAL三步法&#xff1a; 1、配置下载线 2、配置晶振 3、配置时钟 4、 配置灯引脚属性为输出模式。并设置标签为LED 5、配置串口1 串口常用函数说明&#xff1a; 需要实现的伪代码&#xff1a; 示例&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1u6FamKgZhvcEsFAdgGeaw…

Realsense D455 imu 数据不输出?

现象 realsense_viewer 可以可视化查看imu数据, 但是realsense-ros 查看/camera/accel/sample和/camera/gyro/sample没有数据输出 背景 realsense_viewer 安装: sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE…

移动通信为啥要用双极化天线?

❝本文简单介绍下移动通信为啥要用双极化天线及其简单概述。 移动通信为啥要用双极化天线&#xff1f; - RFASK射频问问❝本文简单介绍下移动通信为啥要用双极化天线及其简单概述。什么是极化&#xff1f;电磁波的极化通常是用其电场矢量的空间指向来描述&#xff1a;在空间某…

Leetcode 字母异位词分组

这道题目的意思就是&#xff1a;把包含字母字符相同的单词分到同一组。 算法思路&#xff1a; 使用哈希表来解决。 首先将每个字符串进行排序&#xff0c;将排序之后的字符串作为 key&#xff0c;然后将用 key 所对应的异位词组 作为value。然后我们使用 std::pair 来遍历 键…

Vue的学习(三)

目录 一、for循环中key的作用 1‌.提高性能‌&#xff1a; ‌2.优化用户体验‌&#xff1a; ‌3.辅助Vue进行列表渲染‌&#xff1a; 4‌.方便可复用组件的使用‌&#xff1a; 二、methods及computed及wacth的区别 三、过滤器 1.Vue 2 过滤器简介 定义过滤器 使用过滤…

八、适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许不兼容的接口之间进行合作。适配器模式通过创建一个适配器类来转换一个接口的接口&#xff0c;使得原本由于接口不兼容无法一起工作的类可以一起工作。 主要组成部分&#xff1a; 目标…

CUDA-中值滤波算法

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 实现原理 中值滤波是一种常用的图像处理方法&#xff0c;特别适用于去除图像中的脉冲噪声&#xff08;如椒盐噪声&#xff09;。…

基于IOT的供电房监控系统(实物)

aliyun_mqtt.cpp 本次设计利用ESP8266作为系统主控&#xff0c;利用超声波检测门的状态&#xff0c;利用DHT11检测环境温湿度、烟雾传感器检测空气中的气体浓度&#xff0c;利用火焰报警器模块检测火焰状态&#xff0c;使用OLED进行可视化显示&#xff0c;系统显示传感器数据&a…

同相放大器电路设计

1 简介 同相放大电路输入阻抗为运放的极高输入阻抗&#xff08;GΩ级&#xff09;&#xff0c;因此可处理高阻抗输入源信号。同相放大器的共模电压等于输入信号。 2 设计目标 2.1 输入 2.2 输出 2.3 频率 2.4 电源 3 电路设计 根据设计目标&#xff0c;最终设计的电路结构…

python-确定进制

题目描述 6 942 对于十进制来说是错误的&#xff0c;但是对于 13 进制来说是正确的。即 6(13)​ 9(13)​42(13)​&#xff0c;而 42(13)​4 13^12 13^054(10)​。 你的任务是写一段程序读入三个整数 p,q 和 r&#xff0c;然后确定一个进制 B(2≤B≤16) 使得 p qr 。如果 B 有…

Vue3: 使用ref自动补齐.value

目录 一.老版本&#xff08;已经弃用TypeScript Vue Plugin (Volar)&#xff09; 二.新版本&#xff08;Vue - Official&#xff09; 三.勾选后重启VScode 四.效果 VScode中搜索Vue - Official插件 一.老版本&#xff08;已经弃用TypeScript Vue Plugin (Volar)&#xff0…

学习之git的远程仓库操作的常用命令

1 git remote -v 查看当前所有远程地址别名 2 git remote add 别名 远程地址 3 git push 别名 分支&#xff08;本地分支名称&#xff09; 推送本地分支到远程仓库 4 git pull 远程库别名 远程分支别名 拉取远程库分支&#xff08;更新代码&#xff09; 5 git clone 远程库地址…

【时间盒子】-【6.任务页面】在同一个页面新建、编辑任务

Tips: Column组件的使用&#xff1b; color.json资源文件的使用。 一、页面布局 页面分为三个部分&#xff0c;从上往下分别是&#xff1a;标题菜单栏、时间选择器和任务列表。每个部分都可以设计为独立的组件&#xff0c;后续文章分别介绍。 二、新建页面 右击pages目录&…