首先Spring通过读取XML由多方面解析.
1.Application上下文、
2.解析XML、
3.Application上下文消息总线传播进行通知,进行事件触发,从开启容器到关闭容器通过Spring发布消息总线通知上下文该怎样进行一个操作。
4、Spring的刷新机制
5、Spring实例化Bean进行装配
下面我们通过跟踪源码来进行解析
package org.springframework.bean;
/**
* @author pm
* @apiNode MyBean
* @date 2021/8/2217:48
* 稍后要进行实例化的Bean 自定义类
*/
public class MyBean {
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="MyBean" class="org.springframework.bean.MyBean"></bean>
<!-- <bean name="HelloWorld" class="org.springframework.publish.HelloWorld">-->
<!-- <property name="msg" value="hhhhh"></property>-->
<!-- </bean>-->
<!-- <bean name= "eventReceiver" class = "org.springframework.publish.EventReceiver" />-->
</beans>
启动类
package org.springframework.main;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.publish.HelloWorld;
/**
* @author pm
* @apiNode App
* @date 2021/8/2217:49
*/
public class App {
//这里我们是通过ClassPathXmlApplicationContext这个类来解析XML配置文件来装配Bean进行实例化
//首先会进入ClassPathXmlApplicationContext的默认构造函数
public static void main(String[] args) {
BeanFactory bean = new ClassPathXmlApplicationContext("bean.xml");
System.out.println(bean.getBean("MyBean"));
// HelloWorld helloWorld = (HelloWorld) bean.getBean("HelloWorld");
// helloWorld.send();
}
}
下面我们进行跟踪 来到了ClassPathXmlApplicationContext
首先我们进入了第一个断点,通过传入的bean.xml进行读取,我们看到该方法有几个关键参数
1、configLocation 传入的是bean.xml 显而易见后续会通过该方法进行解析
2、refresh 是否对上下文进行刷新,后续会讲到,这里能理解到,当我们要进行Bean实例化之前会进行刷新一次
3、parent 这个参数表示,是否有父级容器,在Spring加载时通过配置文件解析,再通过Application上下文通知会有两个容器产生,一个父容器,一个子容器,当我们只进行单纯的对象装配时,他不会使用到父容器,而是使用子容器。
这里通过this调用了本身的构造函数
在ClassPathXmlApplicationContext 类有参构造函数中我们发现他通过构造函数这里调用了两个方法
1、setConfigLocations 传入的是配置文件信息
2、刷新上下文机制
下面我们点进去看看这个setConfigLocations 其中会对路径 占位符 等进行解析然后返回一个xml
然后我们进入刷新上下文方法看做了什么,这里start方法进行上下文初始化,
他返回的是一个StartupStep类,我们打开该类里面描述了一个上下文的生命周期,通过调用start方法FlightRecorderStartupStep类实现了该方法,返回了上下文启动的操作记录
然后我们往下走,进入了prepareRefresh()方法
在该方法中进行了设置上下文相关属性以及解析XML,发布Spring消息源的预处理
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
// Switch to active.
//上下文启动时间
this.startupDate = System.currentTimeMillis();
//是否关闭上下文
this.closed.set(false);
//上下文是否处于活动状态
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
//资源初始化
// Initialize any placeholder property sources in the context environment.
initPropertySources();
//验证XML
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
//存储预刷新应用程序侦听器。。。
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
//将本地应用程序侦听器重置为预刷新状态。
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
//允许收集早期ApplicationEvents,
// Allow for the collection of early ApplicationEvents,
//将在Multicast可用后发布。。。
//预发布上下文事件
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
往下走
这里通过该方法会引用到AbstractXmlApplicationContext类的loadBeanDefinitions
可以看到已经生成了一个序列化ID,然后生成新的上下文环境,返回一个新的消息对象总之,在该方法中加载资源并且装配Bean,然后通过计数器进行计数
装配Bean,并且刷新,刷新后会经历清除缓存的一系列操作后生成Bean,返回消息对象
这里调用了prepareBeanFactory 方法传入的是刚刚的读取的Bean实例
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
//设置Bean的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
//解析Bean类名并进行返回 进行表达式解析
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
//解析Bean上下文并解析注册
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//上下文解析器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//环境配置
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
//嵌入值解析
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
//加载资源
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
//用于发布消息总线设置上下文
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
//消息资源
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
//设置Application上下文
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
//启动上下文对象
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//自动装配
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
//资源加载器
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
//发布消息总线
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
//上下文对象
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
//加载上下文的Bean监听器
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
//为类型匹配设置临时类加载器。
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
//注册默认环境bean。
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}