Spring IOC 之深入分析 Aware 接口

news2024/9/20 22:34:40

 🎬作者简介:大家好,我是小徐🥇
☁️博客首页:CSDN主页小徐的博客
🌄每日一句:好学而不勤非真好学者

📜 欢迎大家关注! ❤️

AbstractAutowireCapableBeanFactory 的 #doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 方法,主要干三件事情:

  1. 实例化 bean 对象:#createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) 方法。
  2. 属性注入:#populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) 方法。
  3. 初始化 bean 对象:#initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法。

而初始化 bean 对象时,也是干了三件事情:

  1. 激活 Aware 方法
  2. 后置处理器的应用
  3. 激活自定义的 init 方法

这篇主要分析 Aware 接口。

1. Aware 接口

org.springframework.beans.factory.Aware 接口,定义如下:

/**
 * Marker superinterface indicating that a bean is eligible to be
 * notified by the Spring container of a particular framework object
 * through a callback-style method. Actual method signature is
 * determined by individual subinterfaces, but should typically
 * consist of just one void-returning method that accepts a single
 * argument.
 *
 * <p>Note that merely implementing {@link Aware} provides no default
 * functionality. Rather, processing must be done explicitly, for example
 * in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}
 * for examples of processing {@code *Aware} interface callbacks.
 *
 * @author Chris Beams
 * @since 3.1
 */
public interface Aware {

}

Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,实现了该接口的 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。

Aware 接口是一个空接口,实际的方法签名由各个子接口来确定,且该接口通常只会有一个接收单参数的 set 方法,该 set 方法的命名方式为 set + 去掉接口名中的 Aware 后缀,即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName),ApplicationContextAware(setApplicationContext)。

Aware 的子接口需要提供一个 setXxx 方法,我们知道 set 是设置属性值的方法,即 Aware 类接口的 setXxx 方法其实就是设置 xxx 属性值的。 Aware 的含义是感知的、感应的,那么在 Spring 容器中是如何实现感知并设置属性值得呢?我们可以从初始化 bean 中的激活 Aware 的方法 #invokeAwareMethods(final String beanName, final Object bean) 中看到一点点,代码如下:

// AbstractAutowireCapableBeanFactory.java

private void invokeAwareMethods(final String beanName, final Object bean) {
	if (bean instanceof Aware) {
	    // BeanNameAware
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		// BeanClassLoaderAware
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		// BeanFactoryAware
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}
  • 首先,判断 bean 实例是否属于 Aware 接口的范畴,如果是的话,则调用实例的 setXxx() 方法给实例设置 xxx 属性值,在 #invokeAwareMethods(...) 方法,主要是设置 beanName,beanClassLoader、BeanFactory 中三个属性值。

2. Aware 子类

Spring 提供了一系列的 Aware 接口,如下图(部分):上面只是一部分子类,从这里我们可以看到 Spring 提供的 Aware 接口是是何其多。同时从上图我们也看到了几个比较熟悉的接口,如 BeanClassLoaderAware、BeanFactoryAware、BeanNameAware,下面就这三个接口来做一个简单的演示,先看各自的定义:

public interface BeanClassLoaderAware extends Aware {

    /**
    * 将 BeanClassLoader 提供给 bean 实例回调
    * 在 bean 属性填充之后、初始化回调之前回调,
    * 例如InitializingBean的InitializingBean.afterPropertiesSet()方法或自定义init方法
    */
    void setBeanClassLoader(ClassLoader classLoader);

}


public interface BeanFactoryAware extends Aware {
    /**
    * 将 BeanFactory 提供给 bean 实例回调
    * 调用时机和 setBeanClassLoader 一样
    */
    void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}


public interface BeanNameAware extends Aware {

    /**
    * 在创建此 bean 的 bean工厂中设置 beanName
    */
    void setBeanName(String name);

}


public interface ApplicationContextAware extends Aware {

    /**
     * 设置此 bean 对象的 ApplicationContext,通常,该方法用于初始化对象
     */
    void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException;

}

2.1 示例

下面简单演示下上面四个接口的使用方法:

public class MyApplicationAware implements BeanNameAware,BeanFactoryAware,BeanClassLoaderAware,ApplicationContextAware{

    private String beanName;

    private BeanFactory beanFactory;

    private ClassLoader classLoader;

    private ApplicationContext applicationContext;

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法");
        this.classLoader = classLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("调用了 BeanFactoryAware 的 setBeanFactory 方法");
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("调用了 BeanNameAware 的 setBeanName 方法");
        this.beanName = name;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("调用了 ApplicationContextAware 的 setApplicationContext 方法");
        this.applicationContext = applicationContext;
    }

    public void display(){
        System.out.println("beanName:" + beanName);
        System.out.println("是否为单例:" + beanFactory.isSingleton(beanName));
        System.out.println("系统环境为:" + applicationContext.getEnvironment());
    }
}

测试方法如下:

public static void main(String[] args) {
    ClassPathResource resource = new ClassPathResource("spring.xml");
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinitions(resource);

    MyApplicationAware applicationAware = (MyApplicationAware) factory.getBean("myApplicationAware");
    applicationAware.display();
}

运行结果:从该运行结果可以看出,这里只执行了三个 Aware 接口的 set 方法,原因就是通过 #getBean(...) 方法调用时,在激活 Aware 接口时只检测了 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 三个 Aware 接口。如果将测试方法调整为下面:

public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    MyApplicationAware applicationAware = (MyApplicationAware) applicationContext.getBean("myApplicationAware");
    applicationAware.display();
}

则运行结果如下:

3. 总结

从本文我们基本上就可以 Aware 真正的含义是什么了?感知,其实是 Spring 容器在初始化主动检测当前 bean 是否实现了 Aware 接口,如果实现了则回调其 set 方法将相应的参数设置给该 bean ,这个时候该 bean 就从 Spring 容器中取得相应的资源。

最后文章末尾列出部分常用的 Aware 子接口,便于日后查询:

  • LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
  • BeanClassLoaderAware:加载Spring Bean的类加载器
  • BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
  • ResourceLoaderAware:底层访问资源的加载器
  • BeanFactoryAware:声明BeanFactory
  • PortletConfigAware:PortletConfig
  • PortletContextAware:PortletContext
  • ServletConfigAware:ServletConfig
  • ServletContextAware:ServletContext
  • MessageSourceAware:国际化
  • ApplicationEventPublisherAware:应用事件
  • NotificationPublisherAware:JMX通知
  • BeanNameAware:声明Spring Bean的名字

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

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

相关文章

Leetcode—33. 搜索旋转排序数组【中等】

2024每日刷题&#xff08;110&#xff09; Leetcode—33. 搜索旋转排序数组 实现代码 class Solution { public:int search(vector<int>& nums, int target) {int n nums.size();int l 0, r n - 1;while(l < r) {int m l (r - l) / 2;if(nums[m] target) …

1 月 30 日算法练习-数论

唯一分解定理 唯一分解定理指的是&#xff1a;对于任意一个>1的正整数&#xff0c;都可以以唯一的一种方式分解为若干质因数的乘积。 x p 1 k 1 ⋅ p 2 k 2 ⋅ … ⋅ p m k m x p_1^{k_1} \cdot p_2^{k_2} \cdot \ldots \cdot p_m^{k_m} xp1k1​​⋅p2k2​​⋅…⋅pmkm​…

推荐系统(Recommender Systems)

一、问题形式化 在接下来的内容中&#xff0c;我将开始讲解推荐系统的一些理论知识。我们从一个例子开始定义推荐系统&#xff0c;假使我们是一个电影供应商&#xff0c;我们有 5 部电影和 4 个用户&#xff0c;我们要求用户为电影打分 前三部电影是爱情片&#xff0c;后两部是…

整理:汉诺塔简析

大体上&#xff0c;要解决一个汉诺塔问题&#xff0c;就需要解决两个更简单的汉诺塔问题 以盘子数量 3 的汉诺塔问题为例 要将 3 个盘子从 A 移动到 C&#xff0c;就要&#xff1a; 将两个盘子从 A 移动到 B&#xff08;子问题 1&#xff09; 为了解决子问题 1&#xff0c;就…

图论练习4

内容&#xff1a;染色划分&#xff0c;带权并查集&#xff0c;扩展并查集 Arpa’s overnight party and Mehrdad’s silent entering 题目链接 题目大意 个点围成一圈&#xff0c;分为对&#xff0c;对内两点不同染色同时&#xff0c;相邻3个点之间必须有两个点不同染色问构…

高端酒店宴会包间桌位预定小程序h5开源版开发

高端酒店宴会包间桌位预定小程序h5开源版开发 餐厅预定桌位系统&#xff0c;支持多店切换预约&#xff0c;提供全部前后台无加密源代码和数据库 功能特性 为你介绍餐厅预订系统的功能特性 多端适配 采用uniapp,目前适配小程序和微信H5 多店铺 支持多店铺预定 付费和免费预定 支…

数据结构中的时间复杂度和空间复杂度基础

目录 数据结构 数据结构中的基本名词 数据 数据对象 数据元素 数据项 数据类型 数据对象、数据元素和数据项之间的关系 数据结构及分类 逻辑结构 物理结构 算法 算法的特点 算法设计上的要求 算法效率的衡量 时间复杂度 大O渐进表示法 最坏情况和平均情况 常…

【Simulink系列】——动态系统仿真 之 离散系统线性离散系统

一、离散系统定义 离散系统是指系统的输入与输出仅在离散的时间上取值&#xff0c;而且离散的时间具有相同的时间间隔。满足下列条件&#xff1a; ①系统&#xff08;的输入输出&#xff09;每隔固定时间间隔才更新一次。固定时间间隔称为采样时间。 ②系统的输出依赖当前的…

【Spring】Spring 启示录

一、OCP 开闭原则 核⼼&#xff1a;在扩展系统功能时不需要修改原先写好的代码&#xff0c;就是符合OCP原则的&#xff0c;反之修改了原先写好的代码&#xff0c;则违背了OCP原则的 若在扩展系统功能时修改原先稳定运⾏程序&#xff0c;原先的所有程序都需要进⾏重新测试&…

景区导览系统|智能导览|景区电子导览|智慧景区导览|AI智能导览

景区/园区导览系统是必不可少的服务内容&#xff0c;可提供提供指引导航&#xff0c;讲解景点、VR游览、预约购票等服务。随着元宇宙、VR、AR等数字科技的不断发展&#xff0c;导览系统的形式也从传统的纸质地图、指示牌等形式&#xff0c;发展为如今的VR/AR智慧导览。 作为国…

【OpenCV人脸检测】写了个智能锁屏小工具!人离开电脑自动锁屏

文章目录 1. 写在前面2. 设计思路3. 人脸检测4. 程序实现 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向感兴趣的朋…

MacOS Mojavev10.14.6

MacOS Mojave v10.14.6系统安装包是一款专为Mac用户设计的操作系统软件包。Mojave是苹果公司为Mac设备开发的一个操作系统版本&#xff0c;它提供了许多新功能和改进&#xff0c;旨在提高Mac用户的使用体验和工作效率。 安装MacOS Mojave v10.14.6系统后&#xff0c;用户可以享…

从0到1入门C++编程——07 基于多态的职工管理系统

文章目录 一、创建管理类及菜单功能实现二、创建职工抽象类三、退出管理程序四、增加职工信息五、读写文件操作六、显示职工信息七、删除职工信息八、修改职工信息九、查找职工信息十、对职工信息排序十一、清空文件内容十二、工程文件构成 本案例中利用C实现一个基于多态的职工…

flask_django_python五金电商网络营销的可视化分析研究

前面部分完成了系统需求分析&#xff0c;了解到新闻数据业务方面的需求&#xff0c;系统主要分为用户管理、五金信息管理、在线留言、系统管理等功能。销的可视化研究&#xff0c;并对这些数据进行处理&#xff0c; 然后对这些数据进行可视化分析和统计。 Python 爬虫技术目前来…

职言圈:华为4年员工,小金库存到100万,但却在事业上升期决定回老家县城考公务员。

“华为4年员工&#xff0c;小金库存到100万&#xff0c;但却在事业上升期决定回老家县城考公务员。只因不想现在赚的钱将来都花在了医院&#xff01;” 互联网大厂员工的薪资高&#xff0c;这是人尽皆知的事了&#xff0c;特别是像华为、百度、绿厂、阿里、鹅厂等这些知名公司…

Leetcode的AC指南 —— 栈与队列 :1047.删除字符串中的所有相邻重复项

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列 &#xff1a;1047.删除字符串中的所有相邻重复项 **。题目介绍&#xff1a;给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&a…

CG-FS 风速传感器 485型三杯式风速计 气象环境监测仪器

产品概述 本产品主要采用优质聚合物碳纤维为原材料&#xff0c;具有良好的防腐、防侵蚀等特点&#xff0c;能够保证仪器长期使用不起锈&#xff0c;同时配合内部顺滑的轴承系统&#xff0c;确保了信息采集的准确性。外型小巧轻便&#xff0c;便于携带和组装&#xff0c;三杯设…

计划赶不上变化!项目团队如何高效管理变更请求?

现实中&#xff0c;即使是计划得再好的项目&#xff0c;有时也需要变更。作为项目经理&#xff0c;管理变更请求是重要的工作之一&#xff0c;以便团队能继续无缝工作&#xff0c;实现项目目标。 变更请求的重要性 变更请求是指修改系统、产品或项目计划的建议&#xff0c;通常…

计算机网络_1.6.1 常见的三种计算机网络体系结构

1.6.1 常见的三种计算机网络体系结构 1、OSI&#xff08;七层协议&#xff09;标准失败的原因2、TCP/IP参考模型3、三种网络体系结构对比 笔记来源&#xff1a; B站 《深入浅出计算机网络》课程 1、OSI&#xff08;七层协议&#xff09;标准失败的原因 &#xff08;1&#xf…

利用ReentrantLock解决死锁----以哲学家问题为例

问题描述 哲学家问题&#xff1a;其中多个哲学家在共享有限资源&#xff08;筷子&#xff09;的情况下进行工作&#xff08;思考和吃饭&#xff09;&#xff0c;这可能导致死锁。 每位哲学家需要两根筷子才能吃饭&#xff0c;而每根筷子只能被一位哲学家使用&#xff0c;这就…