上一章节我们讲的是Spirng中的一些核心类,包括IOC容器工厂,和配置解析的一些类,这一章主要是跟一下IOC启动流程。这里我先贴一下IOC的启动部分流程图,在后面的源码分析就是在走这张图,为什么是部分流程图,因为我先分多篇文章来写IOC启动流程,太长了看起来费劲。我把IOC启动流程分为4个阶段:容器创建 -> 配置加载 -> Bean的解析 -> Bean的注册,如下:
源码分析入口从 ClasspathXmlApplicationContext 开始,通过它来加载一个配置
//加载Spring配置文件,拿到Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("配置文件.xml")
//从容器中拿到对象实例
MyBean myBean = context.getBean(MyBean.class);
进入ClassPathXmlApplicationContext构造器可以看到,该构造器接收一个配置文件,构造器的注释是这一样描述的:创建一个新的 ClassPathXmlApplicationContext,从给定的 XML 文件加载定义并自动刷新上下文。
/**
创建一个新的 ClassPathXmlApplicationContext,从给定的 XML 文件加载定义并自动刷新上下文。
* Create a new ClassPathXmlApplicationContext, loading the definitions
* from the given XML file and automatically refreshing the context.
* @param configLocation resource location
* @throws BeansException if context creation failed
*/
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
//调用父类的构造器
super(parent);
//设置位置文件地址
setConfigLocations(configLocations);
if (refresh) {
//刷新容器【重点】
refresh();
}
}
在ClasspathXmlApplication的构造器中做了如下事情:
- 调用了父容器的构造器方法,目的是加载设置Bean的资源加载器
ResourcePatternResolver
- 然后通过
setConfigLocations
方法保存好配置文件地址, - 最后调用
refresh()
刷新容器
ResourcePatternResolver是Bean的资源加载器 ,通过父容器 AbstractApplicationContext 中的构造方法创建:
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
//加载 resourcePatternResolver
this();
//
setParent(parent);
}
/**
* Create a new AbstractApplicationContext with no parent.
*/
//创建一个AbstractApplicationContext容器工厂,并构建一个ResourcePatternResolver
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
//获取 PathMatchingResourcePatternResolver
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
//资源加载器
this.resourceLoader = resourceLoader;
}
父容器AbstractApplicationContext 继承了 DefaultResourceLoader ,拥有资源加载的能力,在构造器中中创建了ResourcePatternResolver,使用的是PathMatchingResourcePatternResolver
作为实现,它能够将指定的资源位置路径解析为一个或多个匹配的资源。 下面是ResourceLoader 源码:
public interface ResourceLoader {
//默认从classpath中加载资源文件
/** Pseudo URL prefix for loading from the class path: "classpath:". */
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
//把资源文件转换成Resource
Resource getResource(String location);
ClassLoader getClassLoader();
}
public interface ResourcePatternResolver extends ResourceLoader {
//从classpath加载资源
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
//把文件转换成Resource[] ,对ResourceLoader做了扩展
Resource[] getResources(String locationPattern) throws IOException;
}
setConfigLocations 保存配置地址
然后就是保存配置地址 ,从源码可以看出,我们是可以传入多个配置文件给容器的。
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
implements BeanNameAware, InitializingBean {
//地址保存到这里
@Nullable
private String[] configLocations;
/**
* Set the config locations for this application context.
* If not set, the implementation may use a default as appropriate.
*/
//可以传入多个配置
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?