这篇文章我们分析SpringApplication#run第8步.执行prepareContext方法.该方法的内容比较多.我们慢慢来.
SpringApplication#run 第8步执行如下代码:
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 1. 上下文设置环境
context.setEnvironment(environment);
// 2. 调用postProcessApplicationContext方法设置上下文的beanNameGenerator和resourceLoader(如果SpringApplication有的话)
postProcessApplicationContext(context);
// 3. 拿到之前实例化SpringApplication对象的时候设置的ApplicationContextInitializer,调用它们的initialize方法,对上下文做初始化
applyInitializers(context);
// 4. contextPrepareds 是一个空实现
listeners.contextPrepared(context);
// 5. 打印启动日志
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
// 6. 日志往上下文的beanFactory中注册一个singleton的bean,bean的名字是springApplicationArguments,bean的实例是之前实例化的ApplicationArguments对象
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
// 如果之前获取的printedBanner不为空,那么往上下文的beanFactory中注册一个singleton的bean,bean的名字是springBootBanner,bean的实例就是这个printedBanner
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
Set
做了8件事:
为上下文设置Environment. 注意 这里传入的是 StandardServletEnvironment
调用postProcessApplicationContext方法设置上下文的beanNameGenerator和resourceLoader(如果SpringApplication有的话)
为上下文设置Environment 执行的是AnnotationConfigEmbeddedWebApplicationContext#setEnvironment,代码如下:
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
3件事:
调用父类的setEnvironment方法.代码如下:
public void setEnvironment(ConfigurableEnvironment environment) {
this.environment = environment;
}
为AnnotatedBeanDefinitionReader设置Environment.执行如下代码.
public void setEnvironment(Environment environment) {
this.conditionEvaluator = new ConditionEvaluator(this.registry, environment, null);
}
实例化了ConditionEvaluator.其构造器如下:
public ConditionEvaluator(BeanDefinitionRegistry registry, Environment environment, ResourceLoader resourceLoader) {
this.context = new ConditionContextImpl(registry, environment, resourceLoader);
}
在实例化ConditionEvaluator时实例化了ConditionContextImpl.该类是ConditionContext的一个实现.是Condition使用时的上下文.其构造器如下:
public ConditionContextImpl(BeanDefinitionRegistry registry, Environment environment, ResourceLoader resourceLoader) {
this.registry = registry;
this.beanFactory = deduceBeanFactory(registry);
this.environment = (environment != null ? environment : deduceEnvironment(registry));
this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry));
}
设置beanFactory.执行如下代码:
private ConfigurableListableBeanFactory deduceBeanFactory(BeanDefinitionRegistry source) {
if (source instanceof ConfigurableListableBeanFactory) {
return (ConfigurableListableBeanFactory) source;
}
if (source instanceof ConfigurableApplicationContext) {
return (((ConfigurableApplicationContext) source).getBeanFactory());
}
return null;
}
由于AnnotationConfigEmbeddedWebApplicationContext是ConfigurableApplicationContext的子类,因此会调用getBeanFactory获得ConfigurableListableBeanFactory.代码如下:
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
返回的是DefaultListableBeanFactory.
设置environment.由于environment不为null,因此不会执行deduceEnvironment.因此直接设置为StandardServletEnvironment.
设置resourceLoader.由于传入的resourceLoader 为null,因此会执行deduceResourceLoader.代码如下;
private ResourceLoader deduceResourceLoader(BeanDefinitionRegistry source) {
if (source instanceof ResourceLoader) {
return (ResourceLoader) source;
}
return null;
}
同样的,由于AnnotationConfigEmbeddedWebApplicationContext是ResourceLoader的子类,因此向上转型为ResourceLoader进行赋值.
为ClassPathBeanDefinitionScanner设置Environment.执行如下代码.
public void setEnvironment(Environment environment) {
Assert.notNull(environment, "Environment must not be null");
this.environment = environment;
this.conditionEvaluator = null;
}
SpringApplication#prepareContext 接下来执行的是 postProcessApplicationContext 方法.设置上下文的beanNameGenerator和resourceLoader(如果SpringApplication有的话).代码如下:
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext) context)
.setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context)
.setClassLoader(this.resourceLoader.getClassLoader());
}
}
}
2件事:
如果resourceLoader不为null的话
接下来执行第3步.代码如下:
protected void applyInitializers(ConfigurableApplicationContext context) {
// 1. 从SpringApplication类中的initializers集合获取所有的ApplicationContextInitializer
for (ApplicationContextInitializer initializer : getInitializers()) {
// 2. 循环调用ApplicationContextInitializer中的initialize方法
Class> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
2件事:
从SpringApplication类中的initializers集合获取所有的ApplicationContextInitializer.将其封装为LinkedHashSet.
遍历之,调用其initialize 进行初始化.当前的initialize有如下:
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
org.springframework.boot.context.ContextIdApplicationContextInitializer,
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer,
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
我们分别看下其initialize 的实现.
代码如下:
public void initialize(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
// 1. 通过env获取到context.initializer.classes配置的值,如果有则直接获取到具体的值并进行实例化
List> initializerClasses = getInitializerClasses(environment);
if (!initializerClasses.isEmpty()) {
applyInitializerClasses(context, initializerClasses);
}
}
还是3步
调用getInitializerClasses获得通过context.initializer.classes 设置的class.
代码如下:
private static final String PROPERTY_NAME = "context.initializer.classes";
private List> getInitializerClasses(ConfigurableEnvironment env) {
String classNames = env.getProperty(PROPERTY_NAME);
List> classes = new ArrayList>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
classes.add(getInitializerClass(className));
}
}
return classes;
}
3步:
调用getInitializerClass 进行加载.代码如下:
private Class> getInitializerClass(String className) throws LinkageError {
try {
// 1. 进行加载
Class> initializerClass = ClassUtils.forName(className,
ClassUtils.getDefaultClassLoader());
// 2. 要加载的类必须是ApplicationContextInitializer 实现才行
Assert.isAssignable(ApplicationContextInitializer.class, initializerClass);
return initializerClass;
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load context initializer class [" + className + "]", ex);
}
}
如果有配置的话,就掉用applyInitializerClasses方法进行初始化. 代码如下:
private void applyInitializerClasses(ConfigurableApplicationContext context,
List> initializerClasses) {
Class> contextClass = context.getClass();
List> initializers = new ArrayList>();
for (Class> initializerClass : initializerClasses) {
initializers.add(instantiateInitializer(contextClass, initializerClass));
}
applyInitializers(context, initializers);
}
2件事.
实例化完毕后调用applyInitializers,依次调用其initialize方法.代码如下:
private void applyInitializers(ConfigurableApplicationContext context,
List> initializers) {
// 排序后调用具体ApplicationContextInitializer类中的initialize方法
Collections.sort(initializers, new AnnotationAwareOrderComparator());
for (ApplicationContextInitializer initializer : initializers) {
initializer.initialize(context);
}
}
代码如下:
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.setId(getApplicationId(applicationContext.getEnvironment()));
}
3件事:
调用getApplicationId 生成id.代码如下
private String getApplicationId(ConfigurableEnvironment environment) {
String name = environment.resolvePlaceholders(this.name);
String index = environment.resolvePlaceholders(INDEX_PATTERN);
String profiles = StringUtils
.arrayToCommaDelimitedString(environment.getActiveProfiles());
if (StringUtils.hasText(profiles)) {
name = name + ":" + profiles;
}
if (!"null".equals(index)) {
name = name + ":" + index;
}
return name;
}
5件事.
获取索引.从以下几个属性中获得.
默认是null
举例说明. 假如我配置 spring.profiles.active=test.端口号为8881,则最后生成的id为application:test:8881
对applicationContext 设置id.代码如下:
public void setId(String id) {
this.id = id;
}
代码如下:
public void initialize(ConfigurableApplicationContext context) {
context.addBeanFactoryPostProcessor(
new ConfigurationWarningsPostProcessor(getChecks()));
}
向context中添加一个ConfigurationWarningsPostProcessor.
在实例化ConfigurationWarningsPostProcessor时首先会调用getChecks获得Check[],传入到ConfigurationWarningsPostProcessor的构造器中.代码如下:
protected Check[] getChecks() {
return new Check[] { new ComponentScanPackageCheck() };
}
其返回了一个ComponentScanPackageCheck. 其初始化的代码如下:
private static final Set<String> PROBLEM_PACKAGES;
static {
Set<String> packages = new HashSet<String>();
packages.add("org.springframework");
packages.add("org");
PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
}
将org.springframework,org 加入到了PROBLEM_PACKAGES 中.
ConfigurationWarningsPostProcessor 构造器如下:
public ConfigurationWarningsPostProcessor(Check[] checks) {
this.checks = checks;
}
这样 ConfigurationWarningsPostProcessor 就持有了ComponentScanPackageCheck.
代码如下:
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.addApplicationListener(
new ApplicationListener() {
@Override
public void onApplicationEvent(
EmbeddedServletContainerInitializedEvent event) {
ServerPortInfoApplicationContextInitializer.this
.onApplicationEvent(event);
}
});
}
向applicationContext 添加一个监听.当发生EmbeddedServletContainerInitializedEvent时间时.会执行ServerPortInfoApplicationContextInitializer#onApplicationEvent方法.将server.ports添加到名为server.ports 的MapPropertySource
代码如下:
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.addBeanFactoryPostProcessor(
new CachingMetadataReaderFactoryPostProcessor());
}
向applicationContext 添加了一个CachingMetadataReaderFactoryPostProcessor 的BeanFactoryPostProcessor
代码如下:
public void initialize(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
applicationContext.addApplicationListener(new AutoConfigurationReportListener());
if (applicationContext instanceof GenericApplicationContext) {
// Get the report early in case the context fails to load
this.report = ConditionEvaluationReport
.get(this.applicationContext.getBeanFactory());
}
}
2件事
如果applicationContext是GenericApplicationContext子类的话,就调用ConditionEvaluationReport#get生成ConditionEvaluationReport.代码如下:
public static ConditionEvaluationReport get(
ConfigurableListableBeanFactory beanFactory) {
synchronized (beanFactory) {
ConditionEvaluationReport report;
if (beanFactory.containsSingleton(BEAN_NAME)) {
report = beanFactory.getBean(BEAN_NAME, ConditionEvaluationReport.class);
}
else {
report = new ConditionEvaluationReport();
beanFactory.registerSingleton(BEAN_NAME, report);
}
locateParent(beanFactory.getParentBeanFactory(), report);
return report;
}
}
调用locateParent.代码如下:
private static void locateParent(BeanFactory beanFactory,
ConditionEvaluationReport report) {
if (beanFactory != null && report.parent == null
&& beanFactory.containsBean(BEAN_NAME)) {
report.parent = beanFactory.getBean(BEAN_NAME,
ConditionEvaluationReport.class);
}
}
这里很明显,由于当前环境下 AnnotationConfigEmbeddedWebApplicationContext 中的BeanFactory 是顶层容器,因此 其 ParentBeanFactory 是不存在的,因此该方法是不会执行的.
代码如下:
public void initialize(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
applicationContext.addApplicationListener(new AutoConfigurationReportListener());
if (applicationContext instanceof GenericApplicationContext) {
// Get the report early in case the context fails to load
this.report = ConditionEvaluationReport
.get(this.applicationContext.getBeanFactory());
}
}
3件事:
如果当前的applicationContext 是GenericApplicationContext 实例的话,就给report进行赋值.很明显,会执行赋值的.执行如下代码:
public static ConditionEvaluationReport get(
ConfigurableListableBeanFactory beanFactory) {
synchronized (beanFactory) {
ConditionEvaluationReport report;
if (beanFactory.containsSingleton(BEAN_NAME)) {
report = beanFactory.getBean(BEAN_NAME, ConditionEvaluationReport.class);
}
else {
report = new ConditionEvaluationReport();
beanFactory.registerSingleton(BEAN_NAME, report);
}
locateParent(beanFactory.getParentBeanFactory(), report);
return report;
}
}
2件事:
很明显,这里是不存在父容器的,并且beanFactory是不包含autoConfigurationReport的定义,因此会实例化后再进行注册.
视线回到SpringApplication#prepareContext中的第5步,打印日志.代码如下:
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
3件事
调用logStartupInfo进行打印.代码如下:
protected void logStartupInfo(boolean isRoot) {
if (isRoot) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarting(getApplicationLog());
}
}
由于此时的context为顶级容器,因此为实例化StartupInfoLogger,实例化时将启动类传入构造器,然后调用其logStarting方法.调用时,首先getApplicationLog获得启动类的log.代码如下:
protected Log getApplicationLog() {
if (this.mainApplicationClass == null) {
return logger;
}
return LogFactory.getLog(this.mainApplicationClass);
}
由于此时的mainApplicationClass不为null,因此会实例化启动类的Log.
public void logStarting(Log log) {
Assert.notNull(log, "Log must not be null");
if (log.isInfoEnabled()) {
log.info(getStartupMessage());
}
if (log.isDebugEnabled()) {
log.debug(getRunningMessage());
}
}
2件事:
如果日志级别是info的话,调用getStartupMessage进行打印.代码如下:
private String getStartupMessage() {
StringBuilder message = new StringBuilder();
message.append("Starting ");
message.append(getApplicationName());
message.append(getVersion(this.sourceClass));
message.append(getOn());
message.append(getPid());
message.append(getContext());
return message.toString();
}
会打印启动类名,启动类所在的版本号,主机名,进程id,上下文.打印的日志如下;
2017-12-25 10:25:22.276 INFO 50826 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on localhost with PID 50826 (/Users/hejiarui/Documents/spring-boot-source/demo/target/classes started by hejiarui in /Users/hejiarui/Documents/spring-boot-source/demo)
如果日志级别是debug的话,调用getRunningMessage进行打印.代码如下:
private StringBuilder getRunningMessage() {
StringBuilder message = new StringBuilder();
message.append("Running with Spring Boot");
message.append(getVersion(getClass()));
message.append(", Spring");
message.append(getVersion(ApplicationContext.class));
return message;
}
打印spring boot 的版本号,ApplicationContext的版本号,打印如下:
2017-12-25 10:29:02.626 DEBUG 50852 --- [ main] com.example.demo.DemoApplication : Running with Spring Boot, Spring v4.3.13.RELEASE
第7步代码如下:
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// 1. 实例化BeanDefinitionLoader
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
// 2. 如果当前的beanNameGenerator 不会null的话,就将SpringApplication中的beanNameGenerator赋值给BeanDefinitionLoader
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
// 3. 如果当前的resourceLoader 不会null的话,就将SpringApplication中的resourceLoader赋值给BeanDefinitionLoader
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
// 4. 如果当前的environment 不会null的话,就将SpringApplication中的environment赋值给BeanDefinitionLoader
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
// 5. 调用load方法进行加载
loader.load();
}
5件事:
实例化BeanDefinitionLoader.代码如下:
protected BeanDefinitionLoader createBeanDefinitionLoader(
BeanDefinitionRegistry registry, Object[] sources) {
return new BeanDefinitionLoader(registry, sources);
}
构造器如下:
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
5件事.
判断是否是在groovy的环境中,如果是的话,就实例化GroovyBeanDefinitionReader.一般情况下,是不会实例化的.判断代码如下:
private boolean isGroovyPresent() {
return ClassUtils.isPresent("groovy.lang.MetaClass", null);
}
如果当前的beanNameGenerator 不会null的话,就将SpringApplication中的beanNameGenerator赋值给BeanDefinitionLoader.对于当前是不会进行赋值的.
调用load方法进行加载.代码如下:
public int load() {
int count = 0;
for (Object source : this.sources) {
count += load(source);
}
return count;
}
2件事:
遍历sources,进行加载.
代码如下:
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class>) {
return load((Class>) source);
}
if (source instanceof Resource) {
return load((Resource) source);
}
if (source instanceof Package) {
return load((Package) source);
}
if (source instanceof CharSequence) {
return load((CharSequence) source);
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
判断source 的类型,然后调用相应的load方法进行加载,由于我们此时传入的是启动类,因此会调用如下方法,代码如下:
private int load(Class> source) {
if (isGroovyPresent()) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
if (GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
GroovyBeanDefinitionSource.class);
load(loader);
}
}
if (isComponent(source)) {
// 进行注册
this.annotatedReader.register(source);
return 1;
}
return 0;
}
2件事:
如果当前类是Component注解的话,就调用AnnotatedBeanDefinitionReader#register进行加载.判断的方法如下:
private boolean isComponent(Class> type) {
// This has to be a bit of a guess. The only way to be sure that this type is
// eligible is to make a bean definition out of it and try to instantiate it.
if (AnnotationUtils.findAnnotation(type, Component.class) != null) {
return true;
}
// Nested anonymous classes are not eligible for registration, nor are groovy
// closures
if (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass()
|| type.getConstructors() == null || type.getConstructors().length == 0) {
return false;
}
return true;
}
3件事
由于我们在启动类上加了@SpringBootApplication的注解,又由于@SpringBootApplication中存在@SpringBootConfiguration,而@SpringBootConfiguration中又存在@Configuration,最终在@Configuration中存在@Component,因此匹配1,因此返回true.
AnnotatedBeanDefinitionReader#register ,通过遍历annotatedClasses,依次调用registerBean进行加载,代码如下:
public void register(Class>... annotatedClasses) {
for (Class> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
registerBean代码如下:
public void registerBean(Class> annotatedClass) {
registerBean(annotatedClass, null, (Class extends Annotation>[]) null);
}
调用:
public void registerBean(Class> annotatedClass, String name, Class extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
9件事:
实例化AnnotatedGenericBeanDefinition.该类的继承结构如下:
由继承结构可知.会首先实例化AbstractBeanDefinition,执行如下构造器.代码如下:
protected AbstractBeanDefinition() {
this(null, null);
}
调用
protected AbstractBeanDefinition(ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
setConstructorArgumentValues(cargs);
setPropertyValues(pvs);
}
2件事:
调用 setConstructorArgumentValues 实例化constructorArgumentValues.代码如下:
public void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) {
this.constructorArgumentValues =
(constructorArgumentValues != null ? constructorArgumentValues : new ConstructorArgumentValues());
}
由于传入的constructorArgumentValues 为null,因此会实例化ConstructorArgumentValues.
调用setPropertyValues 对propertyValues 进行赋值,代码如下:
public void setPropertyValues(MutablePropertyValues propertyValues) {
this.propertyValues = (propertyValues != null ? propertyValues : new MutablePropertyValues());
}
由于传入的propertyValues为null,因此会实例化MutablePropertyValues.
接下来实例化AnnotatedGenericBeanDefinition,构造器如下:
public AnnotatedGenericBeanDefinition(Class> beanClass) {
setBeanClass(beanClass);
this.metadata = new StandardAnnotationMetadata(beanClass, true);
}
2件事:
如果应该跳过加载的话,就直接return. 判断逻辑如下:
public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
// 如果这个类没有被@Conditional注解所修饰,不会skip
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
// 如果参数中沒有设置条件注解的生效阶段
if (phase == null) {
// 是配置类的话直接使用PARSE_CONFIGURATION阶段
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
// 否则使用REGISTER_BEAN阶段
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List conditions = new ArrayList(); // 要解析的配置类的条件集合
// 获取配置类的条件注解得到条件数据,并添加到集合中
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if (requiredPhase == null || requiredPhase == phase) {
// 阶段不满足条件的话,返回true并跳过这个bean的解析
if (!condition.matches(this.context, metadata)) {
return true;
}
}
}
return false;
}
4件事:
如果参数中沒有设置条件注解的生效阶段
递归调用shouldSkip进行判断.对于当前阶段 ConfigurationPhase为ConfigurationPhase.PARSE_CONFIGURATION.
调用AnnotationScopeMetadataResolver#resolveScopeMetadata解析ScopeMetadata. 代码如下:
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
annDef.getMetadata(), this.scopeAnnotationType);
if (attributes != null) {
metadata.setScopeName(attributes.getString("value"));
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = this.defaultProxyMode;
}
metadata.setScopedProxyMode(proxyMode);
}
}
return metadata;
}
2件事:
因此设置AnnotatedGenericBeanDefinition的scope为singleton
调用AnnotationBeanNameGenerator#generateBeanName生成beanName,代码如下:
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
// 1. 如果当前类是AnnotatedBeanDefinition,就调用determineBeanNameFromAnnotation生成beanName
// 如果生成的beanName不为空的话,直接return。否则进入第2步.
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// 2. Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
}
2件事:
经过层层调用最终会调用AnnotationBeanNameGenerator#buildDefaultBeanName获得name,代码如下:
protected String buildDefaultBeanName(BeanDefinition definition) {
String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
return Introspector.decapitalize(shortClassName);
}
调用AnnotationConfigUtils#processCommonDefinitionAnnotations进行处理.代码如下:
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
if (metadata.isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
}
else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
if (metadata.isAnnotated(DependsOn.class.getName())) {
abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
if (metadata.isAnnotated(Role.class.getName())) {
absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
}
if (metadata.isAnnotated(Description.class.getName())) {
absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
}
}
}
4件事:
如果abd 是AbstractBeanDefinition 子类的话
设置qualifier,依次遍历传入的qualifiers进行如下判断.
由于此时传入qualifier 为null,因此是不会进行遍历的.
调用applyScopedProxyMode,这是有关代理方面的.代码如下:
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
2件事
由于这里的scopedProxyMode为NO,因此是直接进行return的.
视线回到SpringApplication#prepareContext.接下来该执行最后一步了, 调用listeners的contextLoaded方法.代码如下;
public void contextLoaded(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.contextLoaded(context);
}
}
调用EventPublishingRunListener#contextLoaded,代码如下:
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}
2件事
遍历application 中的ApplicationListener,如果listener 实现了ApplicationContextAware的话,就调用其setApplicationContext进行赋值.当前的如下:
org.springframework.boot.context.config.ConfigFileApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.logging.LoggingApplicationListener,
org.springframework.boot.logging.ClasspathLoggingApplicationListener,
org.springframework.boot.autoconfigure.BackgroundPreinitializer,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
只有ParentContextCloserApplicationListener实现了ApplicationContextAware接口.
代码如下:
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent(event);
}
}
调用onApplicationPreparedEvent,代码如下:
private void onApplicationPreparedEvent(ApplicationEvent event) {
this.logger.replayTo(ConfigFileApplicationListener.class);
addPostProcessors(((ApplicationPreparedEvent) event).getApplicationContext());
}
调用
protected void addPostProcessors(ConfigurableApplicationContext context) {
context.addBeanFactoryPostProcessor(
new PropertySourceOrderingPostProcessor(context));
}
最终添加了一个PropertySourceOrderingPostProcessor.
最终会执行LoggingApplicationListener#onApplicationPreparedEvent,向beanFactory注册了一个id为springBootLoggingSystem,class 为 LoggingSystem 的bean.
没有做任何事
没有做任何事