spring源码学习(二)——ConfigurationClassPostProcessor(BeanFactory后置处理器的执行)
spring源码学习(三)——初始化bean
spring源码学习(四)——aop
spring两个重要的概念ioc和aop,整个框架是非常复杂的。下面主要了解一下,他们大致的一个流程。
1.1 BeanFactory和ApplicationContext
BeanFactory是spring 的顶层容器,他定义了所有ioc容器必须遵从的原则,拥有实例化对象和获取对象的功能。而ApplicationContext是他的子类,增加了很多额外的功能。不同的实现也增加了不一样的功能,Spring IoC 容器继承体系⾮常聪明,需要使⽤哪个层次⽤哪个层次即可,不必使⽤功能⼤⽽全。
1.2 初始化ioc
本文介绍spring的版本为5.2.3,ioc的初始化主要以ClasspathXmlApplicationContext为例。从创建ClassPathXmlApplicationContext开始看看ioc的整个初始化大致的流程。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
//初始化父类
super(parent);
//设置本地的配置信息(解析配置文件给定路径替换占位符等)
setConfigLocations(configLocations);
//完成spring容器的初始化
if (refresh) {
refresh();
}
}
整个容器的初始化流程都在refresh方法里,下面看看AbstractApplicationContext#refresh方法
public void refresh() {
synchronized (this.startupShutdownMonitor) {
// 刷新前的预处理,准备环境
prepareRefresh();
// 获取BeanFactory,加载注册BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// BeanFactory的预准备工作
prepareBeanFactory(beanFactory);
// BeanFactory准备工作完成后进行的后置处理工作,子类实现
postProcessBeanFactory(beanFactory);
// 实例化实现了BeanFactoryPostProcessor接口的Bean,并调用接口方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor(Bean的后置处理器)
registerBeanPostProcessors(beanFactory);
// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
initMessageSource();
// 初始化事件派发器.
initApplicationEventMulticaster();
// 子类重写这个方法,在容器刷新的时候可以自定义逻辑,如创建tomcat,jetty等web服务器
onRefresh();
// 注册实现了ApplicationListener接口的监听器bean
registerListeners();
// 初始化所有剩下的非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// 完成context的刷新,并且发布事件(ContextRefreshedEvent)
finishRefresh();
}
可以看到spring将每个功能都做了封装,在这个方法中,逻辑层次非常明了,大致流程也备注了,下面来看看几个重要的方法都具体做了什么。
1.2.1 获取BeanFactory加载注册BeanDefinition
首先看AbstractApplicationContext#obtainFreshBeanFactory 方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
在refreshBeanFactory()方法后就返回一个beanFactory了。主要的逻辑就在AbstractRefreshableApplicationContext#refreshBeanFactory中了。
protected final void refreshBeanFactory() throws BeansException {
//实例化 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化id
beanFactory.setSerializationId(getId());
//自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖)
customizeBeanFactory(beanFactory);
// 加载应用中的BeanDefinitions
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
这里实例化了一个DefaultListableBeanFactory并设置一些属性,然后加载应用中的BeanDefinitions,具体看看AbstractXmlApplicationContext#loadBeanDefinitions()方法
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//给指定的beanFactory创建一个XmlBeanDefinitionReader读取器对象,用于读取解析xml对象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//给xmlBeanDefinitionReader对象设置一些context上下文中的环境属性
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//提供给子类实现提供一些自定义的初始化策略
initBeanDefinitionReader(beanDefinitionReader);
//真正的去加载BeanDefinitions
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//从Resource资源对象加载BeanDefinitions
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//从xml配置文件加载BeanDefinition对象
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
这里我们用的是xml的配置文件所以走下面的loadBeanDefinitions,接着将配置文件转换成resource资源对象,读取xml信息保存到Document对象中,最后调用XmlBeanDefinitionReader#registerBeanDefinitions方法解析Document为BeanDefinition
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获取已有BeanDefinition的数量
int countBefore = getRegistry().getBeanDefinitionCount();
//注册BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//返回新注册的BeanDefinition数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
将Document解析成BeanDefinition并注册,最后是由DefaultBeanDefinitionDocumentReader#parseBeanDefinitions方法进行
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//对beans的处理
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
//判断element标签是不是默认标签比如bean import alias beans标签
if (delegate.isDefaultNamespace(ele)) {
//解析默认标签元素
parseDefaultElement(ele, delegate);
}
else {
//解析自定义标签根据命名空间获取对应处理器解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// import元素处理
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//alias元素处理
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// bean元素处理
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 嵌套beans处理
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse递归调用
doRegisterBeanDefinitions(ele);
}
}
这里主要是了解BeanDefinition的解析与注册,所以再继续看processBeanDefinition方法
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//解析bean元素为BeanDefinition,但是此时使用BeanDefinitionHolder又包装成了BeanDefinitionHolder对象持有BeanDefinition
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//如果有自定义标签,解析自定义标签,找到命名空间找到对应处理器,进行处理装饰
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//完成BeanDefinition的注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
可以看到解析是在BeanDefinitionParserDelegate#parseBeanDefinitionElement()中进行的,创建一个GenericBeanDefinition对象,解析设置各种参数属性。BeanDefinitionReaderUtils#registerBeanDefinition则是完成BeanDefinitions的注册。
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
获取beanName然后注册到BeanDefinitionRegistry中,具体可以看DefaultListableBeanFactory#registerBeanDefinition方法,首先会检查beanName是否已经注册,如果已经注册而且不允许覆盖直接抛出异常,接着会将BeanDefinition放入beanDefinitionMap,key就是beanName。