一. 简介及项目设定
1.1 微热山丘 介绍
warmhill(微热山丘)是一个参考 Spring 实现 IoC、AOP 特性的小项目。
相比于 Spring 庞杂的分类、层层继承、抽象,warmhill(微热山丘) 里都是简单直接的类、方法调用,核心在于简洁地展现实现原理。
1.2 项目设定及限制
有如下的限定:
1. 所有的 bean 都是单例。
2. bean 只有一个唯一的标识符 id
,没有名字、别名。
3. 所有的 bean 都是立即初始化的,不支持延迟初始化。
4. 对于 BeanPostProcessor
的应用是基于声明的先后顺序。
5. 对于 AOP 的切入点,只支持对方法调用的拦截,不细分 Before/After/Around/Throw
等。
6. 对于 AOP 的配置也是基于 bean 定义的,不支持 <aop:config>
标签。
7. 目前只支持从 XML 方式配置 bean 。
8. bean 的属性目前只支持 String
类型和对其他 bean 的引用,只支持 setter 方法的依赖注入。
二. IoC、AOP 基本概念介绍
-
Resource: 资源。可存放在任意位置,只有一个方法:
InputStream getStream();
。 -
BeanDefinition: bean 的定义信息。
-
BeanDefitionLoader: bean 定义加载类,只有一个方法:
List<BeanDefinition> load();
。 -
BeanFactory: bean 工厂,负责根据 bean 定义创建 bean 的实例。
/**
* 获取指定 bean 。
* @param beanId beanId
* @param <T> 目标 bean 类型
* @return bean 实例
*/
<T> T getBean(String beanId);
/**
* 获取实现了指定类型的所有 Bean 实例。
* @param requiredType 目标 bean 类型
* @param <T> 目标 bean 类型
* @return 实现了指定类型的 bean 实例列表
*/
<T> List<T> getBeans(Class<T> requiredType);
- BeanPostProcessor: 在 bean 的创建过程中对实例进行加工,以透明地添加额外的特性,AOP 就是通过这个机制实现的,事务控制是 AOP 的一个典型应用场景。
Object postProcessBeforInit(Object bean, String beanId);
Object postProcessAfterInit(Object bean, String beanId);
- ApplicationContext: 应用上下文,继承了
BeanFactory
。职责:
- 根据应用提供的资源信息创建
Resource
, 用BeanDefitionLoader
加载 bean 定义,并注册到BeanFactory
的实现类。 - 管理应用的生命周期,可以重新加载 bean 。
三. IoC 实现要点
IoC 的核心是由 bean 容器创建 bean,并注入 bean 的依赖对象。* AbstractBeanFactory
bean 工厂实现的核心。
3.1 AbstractBeanFactory
的主要属性
List<String> beanIds
属性维护 bean 的声明顺序;Map<String, BeanDefinition> definitionMap
提升根据 beanId 获取 bean 实例的效率。List<BeanPostProcessor> processors
容器里所有的BeanPostProcessor
实现。
3.2 bean 容器初始化的核心流程
- 创建所有的
BeanPostProcessor
实例,以便对后续其他 bean 创建过程进行介入处理。 - 创建其他的 bean 实例,所有 bean 的创建过程中都会应用也有的
BeanPostProcessor
实例。
> 2.1 创建原始类型的实例;
> 2.2 注入依赖的属性;
> 2.3 对原始类型的实例逐个应用BeanPostProcessor
,返回加工后的对公;
> 2.4 把加工后的对象注册到容器里。
代码如下:
// 触发所有 bean 创建的方法
public void refresh() {
// 创建所有的 BeanPostProcessor 实例
initBeanpostProcess();
// 创建其他的 bean 实例
initRemain();
}
private void initRemain() {
beanIds.forEach(beanId -> getBean(beanId));
}
private void initBeanpostProcess() {
processors = getBeans(BeanPostProcessor.class);
}
@Override
public <T> T getBean(String beanId) {
BeanDefinition bdf = definitionMap.get(beanId);
Object bean = bdf.getBean();
if (bean == null) {
// 1. 创建原始类型的实例
bean = createBean(bdf);
// 2. 注入依赖的属性
applyProperties(bean, bdf.getPropertyValues());
// 3. 加工
bean = processBean(bean, bdf);
// 4. 作为最终的结果 bean
bdf.setBean(bean);
}
return (T) bean;
}
protected void applyProperties(Object bean, PropertyValues propertyValues) {
}
// 对原始的 bean 实例进行加工,返回加工后的对象
private Object processBean(Object bean, BeanDefinition bdf) {
for (BeanPostProcessor beanPostProcessor : processors) {
bean = beanPostProcessor.postProcessBeforInit(bean, bdf.getBeanId());
}
// TODO 调用 bean 的初始化方法。
for (BeanPostProcessor beanPostProcessor : processors) {
bean = beanPostProcessor.postProcessAfterInit(bean, bdf.getBeanId());
}
return bean;
}
// 创建原始的 bean 实例
protected Object createBean(BeanDefinition bdf) {
try {
Object o = bdf.getType().newInstance();
return o;
} catch (InstantiationException | IllegalAccessException e) {
throw new BeanCreationException("create bean of " + bdf.getType() + " error .", e);
}
}
/**
* 获取实现了给定类型的所有 bean 实例。
*
* @param requiredType 目标 bean 类型
* @param <T>
* @return 满足条件的实例列表
*/
@Override
public <T> List<T> getBeans(Class<T> requiredType) {
// 按 bean 的声明顺序获取实例
List<Object> beans = beanIds.stream()
.map(beanId -> definitionMap.get(beanId))
.filter(bdf -> requiredType.isAssignableFrom(bdf.getType()))
.map(bdf -> getBean(bdf.getBeanId()))
.collect(Collectors.toList());
return (List<T>) beans;
}
3.3 依赖注入
依赖注入是在 AutoCapableBeanFactory
类完成。
@Override
protected void applyProperties(Object bean, PropertyValues propertyValues) {
// 如果 bean 类型实现了对工厂的监听,则注入工厂实例。
if (BeanFactoryAware.class.isAssignableFrom(bean.getClass())) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
for (PropertyValue propertyValue : propertyValues.getList()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
if (value instanceof BeanReference) {
value = getBean(((BeanReference) value).getBeanId());
}
String setter = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
try {
Method setMethod = bean.getClass().getDeclaredMethod(setter, value.getClass());
setMethod.setAccessible(true);
setMethod.invoke(bean, value);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
try {
Field field = bean.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(bean, value);
} catch (NoSuchFieldException | IllegalAccessException e1) {
throw new BeanCreationException("set property " + name + " error");
}
}
}
}
3.4 构建完整的上下文
应用上下文的两大核心职责:
- 从给定资源加载 bean 定义。
- 用 bean 定义构建 bean 容器工厂。
见 ClasspathApplicationContext
类:
// 1. 创建一个 类路径下的资源
ClasspathResources resources = new ClasspathResources(xmlPath);
// 2. 创建一个 bean 定义加载器并加装 bean 定义
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(resources);
List<BeanDefinition> definitionList = beanDefinitionReader.load();
// 3. 创建 bean 工厂、注册 bean 定义、初始化所有的 bean
AutoCapableBeanFactory beanFactory = new AutoCapableBeanFactory();
definitionList.forEach(beanDefinition -> beanFactory.registerBeanDefinition(beanDefinition));
beanFactory.refresh();
欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。