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:

相关推荐
kk哥88991 天前
如何快速掌握JavaSE的核心语法?
java
我是一只小青蛙8881 天前
AVL树:平衡二叉搜索树原理与C++实战
java·jvm·面试
浩瀚地学1 天前
【Java】JDK8的一些新特性
java·开发语言·经验分享·笔记·学习
XXOOXRT1 天前
基于SpringBoot的加法计算器
java·spring boot·后端·html5
阿崽meitoufa1 天前
JVM虚拟机:垃圾收集器和判断对象是否存活的算法
java·jvm·算法
我是苏苏1 天前
C#高级:使用ConcurrentQueue做一个简易进程内通信的消息队列
java·windows·c#
编程小风筝1 天前
Spring 框架如何整合Redis缓存中间件?
redis·spring·缓存
heartbeat..1 天前
数据库基础知识体系:概念、约束、范式与国产产品
java·数据库·学习笔记·国产数据库
PXM的算法星球1 天前
【操作系统】哲学家就餐问题实现详解
java