您当前的位置: 首页 >  spring

墨家巨子@俏如来

暂无认证

  • 1浏览

    0关注

    188博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Spring源码剖析-IOC启动流程(二)

墨家巨子@俏如来 发布时间:2021-06-01 17:19:25 ,浏览量:1

前言

上一章节我们讲的是Spirng中的一些核心类,包括IOC容器工厂,和配置解析的一些类,这一章主要是跟一下IOC启动流程。这里我先贴一下IOC的启动部分流程图,在后面的源码分析就是在走这张图,为什么是部分流程图,因为我先分多篇文章来写IOC启动流程,太长了看起来费劲。我把IOC启动流程分为4个阶段:容器创建 -> 配置加载 -> Bean的解析 -> Bean的注册,如下: 在这里插入图片描述

ClasspathXmlApplicationContext 容器

源码分析入口从 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 资源加载器

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

关注
打赏
1651329177
查看更多评论
0.0653s