Spring 源码分析——Aware 接口实现

Spring 源码分析——Aware 接口实现

本篇文章讨论 Spring 源码中 Aware 接口的实现。

对应 Github 源码完整文档:https://github.com/TyCoding/mini-spring/tree/main/docs/ioc/09-spring-aware

引言

重新回顾 bean 的生命周期流程,我们在之前的章节中已经讲完了 bean 的加载、实例化、属性填充(包括依赖注入和三级缓存的处理);其中包含了两个重要流程就是对AwarePostProcessor接口的实现,这两个接口都是在 bean 实例化或初始化前后影响 bean 的实例化结果,但是他们的侧重点不同:

  • Aware 接口主要是为了将某个特定类型的 bean 或对象注入到其他组件中,在 Bean 创建之后、初始化之前进行处理;Aware 接口通常与容器的生命周期相关,用于在 Bean 创建之后初始化之前,对 Bean 进行一些必要操作;
  • BeanPostProcessor 和 BeanFactoryPostProcessor 接口则更关注于修改 Bean 实例化的过程本身.BeanPostProcessor 接口定义两个方法用于在容器实例化 Bean 对象并完成依赖注入后,将 Bean 对象返回给调用者之前,进行额外的自定义处理;BeanFactoryPostProcessor 接口则更早接入 Bean 实例化过程,在容器实例化 Bean 之前,允许用户修改 Bean 的定义;

举个例子:

  1. BeanFactoryAware 接口允许 Bean 获取当前的 Bean 工厂对象;在AbstractBeanFactory类中就实现了 BeanFactoryAware 接口并定义了setBeanFactory(),用于将当前 Bean 工厂对象注入到 BeanFactory 组件中;
  2. ResourceLoaderAware 接允许 Bean 获取当前的资源加载器对象;在AbstractApplicationContext类就实现了 ResourceLoaderAware 接口并定义了setResourceLoader(),用于将当前资源加载器对象注入到 ApplicationContext 组件中;

注意:

在 Spring 容器内部,Aware 接口实现一般通过 BeanPostProcessor 或者 BeanFactoryPostProcessor 等后置处理器来自定检测并处理所有实现了 Aware 接口的 Bean,并对其进行初始化和注入操作。(也可以简单的认为 Aware 是 PostProcessor 处理器对 Bean 实例注册属性的一部分)

Bean 生命周期流程如下:

Spring 源码分析——Aware 接口实现
image-20230421104222825

Aware

从源码看 Aware 接口有多少子接口:

Spring 源码分析——Aware 接口实现
img
  1. ApplicationContextAware:允许 Bean 获取当前的应用程序上下文对象
  2. BeanFactoryAware:允许 Bean 获取当前的 Bean 工厂对象
  3. ResourceLoaderAware:允许 Bean 获取当前的资源加载器(ResourceLoader)对象
  4. ServletContextAware:允许 Bean 获取当前的 Servlet 上下文对象
  5. ServletConfigAware:允许 Bean 获取当前的 Servlet 配置对象
  6. LoadTimeWeaverAware:允许 Bean 获取当前的类加载器对象;在 Aop 中,通过该接口获取一个增强的类加载器对象;
  7. BeanNameAware:运行 Bean 获取当前的 Bean 名称;当 Bean 需要动态的引用自身的 Bean 名称就需要注入;
  8. ApplicationEventPublisherAware:允许 Bean 获取当前的时间发布器(ApplicationEventPublisher)对象;使用该对象发布应用程序自定义事件,从而支持组件间协作和消息传递;

如何注入

Spring 源码分析——Aware 接口实现
image-20230512151117688

我们知道AbstractAutowireCapableBeanFactory对象是实际实例化 Bean 的核心类,在这里完成了 Bean 的实例化操作并且包含三级缓存处理。

如上从源码的initializeBean函数可以看到一个invokeAwareMethods函数,顾名思义是处理 Aware 接口方法;

定位下面的invokeAwareMethods函数,此函数中首先会判断要实例化的 Bean 是否实现了 Aware 接口,然后再判断是否实现了 BeanNameAware、BeanClassLoader、BeanFactoryAware 接口,然后依次调用对应的setBeanNamesetBeanClassLoadersetBeanFactory方法,举个例子BeanNameAware

Spring 源码分析——Aware 接口实现
image-20230519113739652

setBeanName是实现了 Aware 接口的 BeanNameAware 接口提供的,具体的实现由 BeanNameAware 实现类实现。

可以看到 Aware 接口的实现其实就是特定的阶段,通过 set 函数将指定的参数写入到实例化后的 Bean 对象中。

Ps: 上面的invokeAwareMethods函数中仅仅有这个三个 Aware 子接口的设置,是因为这是在 Bean 实例化的阶段,在这里 Spring 仅需要注入实例化 Bean 所必须的 Aware 接口;而 Aware 的子接口很多,他们分别在不同的生命周期阶段完成注入操作。

Spring 源码专栏

此专栏将从 Spring 源码角度整体分析 Spring 设计思路以及常见的面试题

配套作者的手写 Spring 的项目:https://github.com/TyCoding/mini-spring 。该项目中包含各个阶段的开发文档,有关 Spring 源码更详细的分析测试文档请查阅:https://github.com/TyCoding/mini-spring/tree/main/docs

联系我

  • 个人博客:http://tycoding.cn/
  • GitHub:https://github.com/tycoding
  • 微信公众号:程序员涂陌
  • QQ 交流群:866685601


原文始发于微信公众号(程序员涂陌):Spring 源码分析——Aware 接口实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/145570.html

(0)

及时掌握行业动态,欢迎加入几百人的后端技术交流群:


相关推荐

发表回复

登录后才能评论