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:

相关推荐
唐青枫1 分钟前
Java Liquibase 实战指南:让数据库变更像代码一样可追踪
java
qq_422152575 分钟前
PDF 解密工具怎么选?2026 年文档密码移除方案与注意事项
java·前端·pdf
布朗克16814 分钟前
38 Spring Boot入门——自动配置、核心注解与Starter机制
java·spring boot·后端
沪漂阿龙22 分钟前
LangChain 系列:Structured Output结构化输出与源码解析
java·人工智能·架构·langchain
半夜燃烧的香烟26 分钟前
springboot3.0 集成minio上传文件,支持多个桶名
java·开发语言·spring boot
J2虾虾37 分钟前
Android支持Java语言的标准
android·java·开发语言
Oo_行者_oO1 小时前
Spring Schedule + ShedLock + RabbitMQ 生产级落地方案 - 云楼(中国)
java·后端
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第113题】【并发篇】第13题:说一下乐观锁的优点和缺点?
java·开发语言·面试
Mahir081 小时前
HashMap 底层原理深度解密:从数据结构到 JDK1.7/1.8 演进全解
java·后端·面试·hashmap