mini-spring基础篇:IoC(十一):Aware接口

一、Aware接口

代码分支:aware-interface
之前都是基于main分支来追踪源码,从现在开始,我们基于每章开始的代码分支追踪源码。

mini-spring源码作者建议如此,这样阅读难度会更小。

Aware是感知、意识的意思,Aware接口是标记性接口,其实现子类能感知容器相关的对象。常用的Aware接口有BeanFactoryAware和ApplicationContextAware,分别能让其实现者感知所属的BeanFactory和ApplicationContext。

让实现BeanFactoryAware接口的类能感知所属的BeanFactory,实现比较简单,查看AbstractAutowireCapableBeanFactory#initializeBean前三行。

实现ApplicationContextAware的接口感知ApplicationContext,是通过BeanPostProcessor。由bean的生命周期可知,bean实例化后会经过BeanPostProcessor的前置处理和后置处理。定义一个BeanPostProcessor的实现类ApplicationContextAwareProcessor,在AbstractApplicationContext#refresh方法中加入到BeanFactory中,在前置处理中为bean设置所属的ApplicationContext。

改用dom4j解析xml文件。

至止,bean的生命周期如下:

测试:

spring.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	         http://www.springframework.org/schema/beans/spring-beans.xsd
		 http://www.springframework.org/schema/context
		 http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean id="helloService" class="org.springframework.test.service.HelloService"/>

</beans>
java 复制代码
public class HelloService implements ApplicationContextAware, BeanFactoryAware {

	private ApplicationContext applicationContext;

	private BeanFactory beanFactory;

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = beanFactory;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	public ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	public BeanFactory getBeanFactory() {
		return beanFactory;
	}
}
java 复制代码
public class AwareInterfaceTest {

	@Test
	public void test() throws Exception {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
		HelloService helloService = applicationContext.getBean("helloService", HelloService.class);
		assertThat(helloService.getApplicationContext()).isNotNull();
		assertThat(helloService.getBeanFactory()).isNotNull();
	}
}

二、源码追踪

可以看到HelloService实现了两个接口BeanFactoryAware、ApplicationContextAware。这两个接口都要实现他们各自的方法,分别是设置ApplicationContext、BeanFactory。这两个都是ioc容器。

BeanFactory多用于spring本身,ApplicationContext多用于我们这些使用者。

2.1 BeanFactoryAware源码追踪








DefaultListableBeanFactory对象类图:

2.2 ApplicationContextAware源码追踪

前8步,和【10.1.1】一毛一样,我们从第9步开始看:



2.3 设置完BeanFactory和ApplictionContext之后呢?干了什么

暂时还不懂。

三、应用场景

我有一个类,不归spring管理,但我又想在这个类里操作spring,那么我该如何操作?

3.1 SpringUtil源码:

其中,BeanFactoryPostProcessor是用来修改BeanDefinition的。

3.2 SpringUtil中设计到BeanFactoryPostProcessor部分的源码

实现BeanFactoryPostProcessor接口,需要重写这个方法:

它的入参,要注入一个ConfigurableListableBeanFactory对象。这个其实就是我们前面看到的DefaultListableBeanFactory对象。可以看前面的类图:


这里的对象,就包括了SpringUtil对象!

猜测:

读到这里,我猜测SpringUtil是不是应该被加入到了spring容器里,我猜大概率是通过spi的方式加入进去的。

查看hutool源码,果然印证了我的猜测:

多废话一句,对第【5】步做一个补充:

废话说完了,继续第6步:

只是我们之前自定义的CustomBeanFactoryPostProcessor:

hutool的SpringUtil:

相关推荐
秋天的怀念_David5 小时前
算法一千零一夜 · 第十四夜 幻方与奇妙的二进制
java·程序人生·算法
thefool1122665 小时前
网络编程^
java
Thinker QAQ5 小时前
并发编程(十一):Shared Memory 与 Message Passing——关系与组合使用
java·python·go·并发编程·shared memory·message passing
齐 飞6 小时前
idea中git误操作撤回git reset --hard ‘HEAD@{1}‘
java·git·intellij-idea
你的保护色6 小时前
多AS互联BGP4综合实验设计
java
某不知名網友6 小时前
ROS2进阶:服务通信、自定义SRV接口、参数服务器与基于服务的参数通信详解
java·开发语言·microsoft
Wang's Blog6 小时前
Java 项目实战: 交友项目 - MongoDB 入门:体系结构和命令行操作
java·mongodb·交友
小溪学编程6 小时前
将 Bean 放入 Spring 容器中的方式有哪些?
java·后端·spring
java_nnnn6 小时前
LeetCode刷题滑动窗口(水果成篮+找到字符串中所有字母的异位词)Java
java·开发语言·leetcode
用户3721574261357 小时前
Java 读取、修改和清空 PDF 文档属性(元数据)
java