关键类介绍
ApplicationContext
万能的 applicationContext, 但实际上各种能力都是依赖于其他的类, 比如 getBean 是 beanFactory 的, publishEvent 是事件广播器的, 等等. 其本身是一个综合体, 整合这些能力, 便于开发者调用和理解.
# 下面列一下相关的接口, 抽象类, 和具体类
ApplicationContext
是一个只读的 bean 容器
可以加载解析配置文件(如xml)
可以发布事件和注册监听
具有国际化消息处理能力
ConfigurableApplicationContext
是一个具有可配置能力的 容器(可设置各个参数, 如id, 父容器)
具有容器生命周期概念, 如启动,停止,关闭.
AbstractApplicationContext
模板方法模式的抽象类, 定义了容器的模板(refresh方法), 但由具体的子类实现部分方法
管理Bean和BeanFactory的PostProcessor
管理事件的监听和处理
AbstractRefreshableApplicationContext
为可重复刷新的容器提供基类
加入了BeanFactory的管理(创建/关闭等)
AbstractRefreshableConfigApplicationContext
加入了configLocation字段, 用于某些容器初始化BeanFactory和Bean
AbstractXmlApplicationContext
定义了读取xml配置文件来加载BeanFactory的代码, 使得子类只需提供配置文件地址或Resource
ClassPathXmlApplicationContext
继承基类, 提供配置文件地址的构造方法, 调用refresh加载BeanFactory
BeanFactory
1.核心中的核心, 加载和管理 beanDefinitions(Bean配置信息), 创建和管理 bean 对象实例, 注册和管理 BeanPostProcessor(Bean扩展)
# 下面列一下相关的接口, 抽象类, 和具体类
BeanFactory
定义了 Bean 的基础操作接口, 如 getBean, getType, isSingleton 等
SingletonBeanRegistry
定义了单例对象的操作接口 (注册/获取/是否已存在)
HierarchicalBeanFactory
定义了父 BeanFactory 的相关操作接口(获取)
ConfigurableBeanFactory
定义了对 BeanFactory 做各种配置的操作接口, 包括 BeanPostProcessor, setParentBeanFactory, destroyBean, registerAlias, resolveAliases 等
DefaultSingletonBeanRegistry
实现了 SingletonBeanRegistry 接口, 即实现了单例对象的缓存管理, 包括一级/二级/三级(二级三级只依赖循环用上的两个缓存)
FactoryBeanRegistrySupport
继承了 DefaultSingletonBeanRegistry
实现对使用 FactoryBean 存储和获取 bean 对象实例方式的支持
AbstractBeanFactory
继承了 FactoryBeanRegistrySupport
实现了 BeanFactory/HierarchicalBeanFactory/ConfigurableBeanFactory 定义的接口
实现了具体 getBean, 包括缓存管理等
AutowireCapableBeanFactory
定义了根据 class 类型获取 BeanDefinition 信息以及 Bean 对象的接口
AbstractAutowireCapableBeanFactory
继承自 AbstractBeanFactory
实现了 AutowireCapableBeanFactory 中定义的方法(就是实现了根据 class 获取 bean 或 BeanDefinition)
实现了 createBean, 也就是真正的实例化一个对象的过程, 包括实例化, 为需要赋值的字段注入相应的值
同时触发了 BeanPostProcessor 的方法调用
BeanDefinitionRegistry
定义了 BeanDefinition 的注册/获取/移除
ListableBeanFactory
定义了 BeanDefinition 的可遍历性
ConfigurableListableBeanFactory
结合 ListableBeanFactory 和 ConfigurableBeanFactory 并补充完善了几个相关接口 (如 getBeanNamesIterator 接口 )
DefaultListableBeanFactory
继承了 AbstractAutowireCapableBeanFactory
实现了 BeanDefinitionRegistry/ConfigurableListableBeanFactory 的接口
# 总结:
定义处:
BeanFactory(getBean)
SingletonBeanRegistry(addSingleton)
HierarchicalBeanFactory(getParentBeanFactory)
ConfigurableBeanFactory(addBeanPostProcessor)
AutowireCapableBeanFactory(autowireBean)
BeanDefinitionRegistry(registerBeanDefinition)
ListableBeanFactory(getBeanDefinitionNames)
ConfigurableListableBeanFactory(getBeanNamesIterator)
实现处:
DefaultSingletonBeanRegistry(registerSingleton)
FactoryBeanRegistrySupport(getObjectFromFactoryBean)
AbstractBeanFactory(doGetBean)
AbstractAutowireCapableBeanFactory(createBean)
DefaultListableBeanFactory(registerBeanDefinition)
容器初始化过程
1.setParent(): 处理父容器
2.setConfigLocations(): 解析并设置xml配置文件路径
3.refresh(): 创建 beanFactory 对象并初始化, 读取 xml 配置文件得到 beanDefinitions, 接着处理两种 PostProcessor, 然后添加国际化处理器和事件广播器以及相应的初始化和一些处理, 最后实例化单例的 bean 等等.
#外圈结束, 再看 refresh() 里面的每个方法
1.prepareRefresh(): 准备工作, 一些字段值的设置和处理.
2.obtainFreshBeanFactory(): 创建一个 beanFactory 对象并注册到 applicationContext (即赋值到字段上), 然后解析 xml 配置文件(或注解配置)的信息, 解析得到 beanDefinitions 并注册到容器中.
3.然后是一些对 beanFactory 对象的完善配置的代码
4.扫描并执行 BeanFactoryPostProcessor(其作用是为beanFactory对象添加东西提供扩展性), 其中我认识的就只有 ConfigurationClassPostProcessor(这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan等基础注解).
5.扫描实现了 BeanPostProcessor 接口的 bean 并注册到 beanFactory 中存起来, 等 createBean 创建对象时会在对应的时机执行一些对应的方法(钩子). 常见的各种 XxxAware 就是靠这个实现的咯.
6.接着, 初始化国际化资源处理器, 事件广播器, 并注册一些需要注册的事件(也注册容器内实现对应接口的 bean)
7.处理一些 beanFactory 的配置, 接着为所有单例且非懒加载的(不就是默认策略嘛) bean 创建实例, 缓存起来.
8.广播容器加载完成了的事件. 以及处理生命周期.
最后总结下, 先创建容器, 再将根据配置文件解析得到 BeanDefinition 注册到容器中, 然后处理两大扩展(BeanFactoryPostProcessor/BeanPostProcessor), 接着是Spring的国际化, 以及相当有用的事件广播器, 最后实例化 bean. 整体感觉其实很简单, 但其实有大量的工作交给了 BeanPostProcessor.
超长源码分析过程
// 先随便写个 main 方法, 如我写的, 可测试依赖循环问题和事件监听:
// 包名: cn.gudqs7.spring.tests, 改动则需同步修改xml哦
// 进入对应类代码: 快捷键 Cmd+Option+鼠标点击 (或 Ctrl+Alt+鼠标左键 ); 如果是接口松开 Option(或Alt)键
Test.java
public class Test {
public static void main(String[] args) {
ApplicationContext xmlContext = new ClassPathXmlApplicationContext("application-wq.xml");
UserServiceImpl userService = xmlContext.getBean(UserServiceImpl.class);
userService.sayHi();
}
}
application-wq.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
<bean name="userService" class="cn.gudqs7.spring.tests.UserServiceImpl">
<property name="starter"><ref bean="serverStarter"/></property>
</bean>
<bean name="serverStarter" class="cn.gudqs7.spring.tests.ServerStarter">
<property name="userService"><ref bean="userService"/></property>
</bean>
</beans>
UserServiceImpl.java
@Service
public class UserServiceImpl {
@Resource
private ServerStarter starter;
public void sayHi() {
System.out.println(starter);
System.out.println("Hello Spring!");
}
public void setStarter(ServerStarter starter) {
this.starter = starter;
}
}
ServerStarter.java
@Service
public class ServerStarter implements ApplicationListener<ContextRefreshedEvent> {
@Inject
private UserServiceImpl userService;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
String applicationName = event.getApplicationContext().getApplicationName();
System.out.println(applicationName);
System.out.println(userService);
System.out.println("========== started by gudqs7 ==============");
System.out.println("========== started by gudqs7 ==============");
System.out.println("========== started by gudqs7 ==============");
}
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
}