一、ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
private final Source source;
private final String[] args;
public DefaultApplicationArguments(String[] args) {
Assert.notNull(args, "Args must not be null");
this.source = new Source(args);
this.args = args;
}
private static class Source extends SimpleCommandLinePropertySource {
Source(String[] args) {
super(args);
}
@Override
public List<String> getNonOptionArgs() {
return super.getNonOptionArgs();
}
@Override
public List<String> getOptionValues(String name) {
return super.getOptionValues(name);
}
}
意思就是将 main方法的参数封装起来。
二、ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
需要提前说明的是,listeners就是我们前面获取的整个run方法的监听器SpringApplicationRunListeners,applicationArguments则封装了main方法的参数,那就看一下这个方法的实现吧:
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
//1、创建ConfigurableEnvironment
ConfigurableEnvironment environment = getOrCreateEnvironment();
//2、配置ConfigurableEnvironment
configureEnvironment(environment, applicationArguments.getSourceArgs());
//3、发布事件
listeners.environmentPrepared(environment);
if (!this.webEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);
}
return environment;
}
上面代码一共标注了该方法执行所经历的三个过程:
1、创建ConfigurableEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
if (this.webEnvironment) {
return new StandardServletEnvironment();
}
return new StandardEnvironment();
}
因为该项目是一个web项目,所以执行new StandardServletEnvironment(),StandardServletEnvironment这个类的继承实现体系如下:
- PropertyResolver:解析属性的规范
- Environment:当前正在运行的应用环境的规范
- ConfigurablePropertyResolver:用户可定制化PropertyResolver在解析和转换property时候的逻辑
- ConfigurableEnvironment:大多数应用环境都要实现此接口,可以设置配置文件等
- ConfigurableWebEnvironment:在ConfigurableEnvironment的基础上,可以初始化与servlet相关的属性资源
- AbstractEnvironment:实现了ConfigurableEnvironment接口,默认属性和存储容器的定义,并且实现了ConfigurableEnvironment种的方法,并且为子类预留可覆盖了扩展方法
- StandardEnvironment:继承自AbstractEnvironment,非Servlet(Web)环境下的标准Environment实现
- StandardServletEnvironment:继承自StandardEnvironment,Servlet(Web)环境下的标准Environment实现
创建StandardServletEnvironment对象的时候,会依次执行如下代码:
private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);
public AbstractEnvironment() {
customizePropertySources(this.propertySources);
if (logger.isDebugEnabled()) {
logger.debug("Initialized " + getClass().getSimpleName() + " with PropertySources " + this.propertySources);
}
}
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
}
super.customizePropertySources(propertySources);
}
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
我们可以看到,一直在往propertySources中添加对象,propertySources是MutablePropertySources类型的,其中维护了一个集合:
public class MutablePropertySources implements PropertySources {
private final Log logger;
private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<PropertySource<?>>();
//将propertySource添加到最低的优先级
public void addLast(PropertySource<?> propertySource) {
if (logger.isDebugEnabled()) {
logger.debug("Adding PropertySource '" + propertySource.getName() + "' with lowest search precedence");
}
removeIfPresent(propertySource);
this.propertySourceList.add(propertySource);
}
}
因为MutablePropertySources的adddLast方法是将参数以最低的优先级添加到CopyOnWriteArrayList中,所以我们可以预见的是,它们的执行顺序为:
new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME)----------》
new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)-------》
new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME)-------------------------------》
new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties())-------------》
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment())
三、Banner printedBanner = printBanner(environment)
这个方法不用看,就是打印一个banner,不涉及任何应用逻辑。
四、context = createApplicationContext();
private Class<? extends ConfigurableApplicationContext> applicationContextClass;
public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."
+ "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
//因为该项目是web环境,所有接下来的工作就是加载org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
接下来加载org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext,该类的继承体系如下图:
构造方法如下:
public AnnotationConfigEmbeddedWebApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
1》初始化reader
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//EnvironmentCapable是一个标识接口,表明该实例是否包含并且暴露一个org.springframework.core.env.Environment的引用,因为该接口实现了ApplicationContext接口,ApplicationContext接口又继承了EnvironmentCapable接口,所以下面的判断为true,其中getEnvironment方法的实现是放在AbstractApplicationContext中,最终会调用org.springframework.web.context.support.GenericWebApplicationContext#createEnvironment去创建一个StandardServletEnvironment
if (registry instanceof EnvironmentCapable) {
return ((EnvironmentCapable) registry).getEnvironment();
}
return new StandardEnvironment();
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
2》初始化scanner
创建扫描器
五、new FailureAnalyzers(context);
FailureAnalyzers(ConfigurableApplicationContext context, ClassLoader classLoader) {
Assert.notNull(context, "Context must not be null");
this.classLoader = (classLoader == null ? context.getClassLoader() : classLoader);
this.analyzers = loadFailureAnalyzers(this.classLoader);
prepareFailureAnalyzers(this.analyzers, context);
}
private void prepareFailureAnalyzers(List<FailureAnalyzer> analyzers,
ConfigurableApplicationContext context) {
for (FailureAnalyzer analyzer : analyzers) {
prepareAnalyzer(context, analyzer);
}
}
private void prepareAnalyzer(ConfigurableApplicationContext context,
FailureAnalyzer analyzer) {
if (analyzer instanceof BeanFactoryAware) {
((BeanFactoryAware) analyzer).setBeanFactory(context.getBeanFactory());
}
}