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:

相关推荐
xcl09254 小时前
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南
java·spring boot·架构
一 乐6 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
卓怡学长7 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn7 小时前
Spring 注解使用详解
java·spring
一条小小yu7 小时前
Spring IoC的理解
java·后端·spring
落魄实习生7 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈7 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白9 小时前
核心功能(Service接口)
java·mybatis
乌暮10 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习