上篇回顾
上一篇SpringBootExceptionReporter异常上报中分析了springboot如何处理启动过程中的异常
目录
1. 准备容器prepareContext()
2. 统一ApplicationContext和Application使用的environment
3. ApplicationContext的后置处理
4. 执行Initializers
4.1 DelegatingApplicationContextInitializer
4.2 SharedMetadataReaderFactoryContextInitializer
4.3 ContextIdApplicationContextInitializer
4.4 ConfigurationWarningsApplicationContextInitializer
4.5 ServerPortInfoApplicationContextInitializer
4.6 ConditionEvaluationReportLoggingListener
5. 发布ApplicationContextInitializedEvent事件
6. 打印启动和profile日志
7. 手工注册单例Bean
8. 初始化BeanDefinitionLoader, 加载Application
9. 发布contextLoaded事件
9.1 ConfigFileApplicationListener
9.2 LoggingApplicationListener
9.3 BackgroundPreinitializer
9.4 DelegatingApplicationListener
1. 准备环境prepareContext()
准备应用上下文环境AnnotationConfigServletWebServerApplicationContext, 执行了以下8个步骤
- 统一ApplicationContext和Application使用的environment
- 后置处理ApplicationContext
- 执行Initializers
- 发布contextPrepared事件
- 打印启动和profile日志
- 注册单例bean
- 加载启动类
- 发布contextLoaded事件
public class SpringApplication {
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//本文的重点
//准备应用上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//...
}
/**
* 准备应用上下文
* @param context AnnotationConfigServletWebServerApplicationContext实例
* @param environment SpringApplication中的StandardServletEnvironment实例
* @param applicationArguments SpringApplication中的DefaultApplicationArguments实例
* @param printedBanner 默认使用SpringApplicationBanner实例
*/
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置context(上下文)环境
//统一ApplicationContext和Application,使用Application的environment
context.setEnvironment(environment);
//ApplicationContext的后置处理
postProcessApplicationContext(context);
//执行Initializers
applyInitializers(context);
//发布contextPrepared事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
//配置了info日志
//打印启动和profile日志
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
//获取到DefaultListableBeanFactory实例
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//注册名为springApplicationArguments,值为applicationArguments的单例bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
//banner不为空,那么注册名为springBootBanner,值为printedBanner的单例bean
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
//allowBeanDefinitionOverriding默认为false
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 获取sources列表,获取到我们的YanggxApplication.class
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//初始化bean加载器,并加载bean到应用上下文
load(context, sources.toArray(new Object[0]));
//发布contextLoaded事件
listeners.contextLoaded(context);
}
}
2. 统一ApplicationContext和Application使用的environment
配置ApplicationContext和Application的environment成员变量, 使用Application的environment, AnnotationConfigServletWebServerApplicationContext的bean定读取器reader和bean扫描器scanner都使用Application的environment
public class AnnotationConfigServletWebServerApplicationContext
extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
//显式调用父类AbstractApplicationContext的setEnvironment方法
super.setEnvironment(environment);
//调用AnnotatedBeanDefinitionReader#setEnvironment()方法
this.reader.setEnvironment(environment);
//ClassPathBeanDefinitionScanner继承了ClassPathScanningCandidateComponentProvider,所以调用了父类setEnvironment方法
this.scanner.setEnvironment(environment);
}
}
显式调用父类AbstractApplicationContext的setEnvironment方法
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
//environment成员变量
@Nullable
private ConfigurableEnvironment environment;
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
this.environment = environment;
}
}
调用AnnotatedBeanDefinitionReader#setEnvironment()方法
public class AnnotatedBeanDefinitionReader {
public void setEnvironment(Environment environment) {
//初始化conditionEvaluator
this.conditionEvaluator = new ConditionEvaluator(this.registry, environment, null);
}
}
调用ClassPathBeanDefinitionScanner的setEnvironment方法
ClassPathBeanDefinitionScanner继承了ClassPathScanningCandidateComponentProvider, 所以调用了父类setEnvironment方法
ublic class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
@Nullable
private Environment environment;
public void setEnvironment(Environment environment) {
Assert.notNull(environment, "Environment must not be null");
this.environment = environment;
//conditionEvaluator置为null
this.conditionEvaluator = null;
}
}
3. ApplicationContext的后置处理
执行了以下三步
- 设置ApplicationContext的beanNameGenerator
- 设置ApplicationContext的resourceLoader和classLoader
- 设置ApplicationContext的类型转换Service
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
//没有设置beanNameGenerator,默认为null
if (this.beanNameGenerator != null) {
//如果beanNameGenerator不为空
//那么注册一个名为internalConfigurationBeanNameGenerator
//值为beanNameGenerator的单例bean
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
//没有设置resourceLoader,默认为null
if (this.resourceLoader != null) {
//如果resourceLoader不为空
if (context instanceof GenericApplicationContext) {
//context是GenericApplicationContext子类
//那么设置上下文context的resourceLoader
((GenericApplicationContext) context)
.setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
//如果当前上下文是DefaultResourceLoader的子类
//那么设置上下文context的classLoader
((DefaultResourceLoader) context)
.setClassLoader(this.resourceLoader.getClassLoader());
}
}
//this.addConversionService默认为true
if (this.addConversionService) {
//设置类型转换Service
context.getBeanFactory().setConversionService(
ApplicationConversionService.getSharedInstance());
}
}
4. 执行Initializers
initializers在SpringApplication初始化期间获取到, 一共获取到6个初始化器:
- DelegatingApplicationContextInitializer
- SharedMetadataReaderFactoryContextInitializer
- ContextIdApplicationContextInitializer
- ConfigurationWarningsApplicationContextInitializer
- ServerPortInfoApplicationContextInitializer
- ConditionEvaluationReportLoggingListener
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
//断言判断initializer的类型是否符合条件
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
//执行各个initializer的初始化initialize方法
initializer.initialize(context);
}
}
4.1 DelegatingApplicationContextInitializer
获取环境中属性context.initializer.classesInitializer配置的ApplicationContextInitializer列表, 执行其initialize()方法, 由于我们没有配置属性context.initializer.classesInitializer, 所以不会执行任何操作
//代理初始化器
public class DelegatingApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
private static final String PROPERTY_NAME = "context.initializer.classes";
@Override
public void initialize(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
//获取environment中配置的context.initializer.classes属性
//其值为各个initializer,用逗号分隔开
List<Class<?>> initializerClasses = getInitializerClasses(environment);
if (!initializerClasses.isEmpty()) {
//获取到各个initializer,并执行其initialize()方法
applyInitializerClasses(context, initializerClasses);
}
}
}
4.2 SharedMetadataReaderFactoryContextInitializer
添加了一个类型为CachingMetadataReaderFactoryPostProcessor的BeanFactoryPostProcessor, CachingMetadataReaderFactoryPostProcessor会做两件事情
- 注册一个名称为internalCachingMetadataReaderFactory, 类型为SharedMetadataReaderFactoryBean的bean, 用于读取bean的元数据Metadata
- 获取名称为internalConfigurationAnnotationProcessor, 类型为ConfigurationClassPostProcessor的bean定义, 为其添加name为metadataReaderFactory, value为internalCachingMetadataReaderFactory的internalCachingMetadataReaderFactory
class SharedMetadataReaderFactoryContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
public static final String BEAN_NAME = "org.springframework.boot.autoconfigure."
+ "internalCachingMetadataReaderFactory";
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//spring上下文容器添加一个CachingMetadataReaderFactoryPostProcessor
applicationContext.addBeanFactoryPostProcessor(
new CachingMetadataReaderFactoryPostProcessor());
}
}
4.3 ContextIdApplicationContextInitializer
初始化容器ID, 获取属性spring.application.name配置的应用名称, 如果不存在的话, 默认使用application
//容器ID初始化器
public class ContextIdApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//获取并设置容器ID
ContextId contextId = getContextId(applicationContext);
applicationContext.setId(contextId.getId());
//容器beanFactory中注册一个名称为ContextId类名
//值为contextId的bean
applicationContext.getBeanFactory().registerSingleton(ContextId.class.getName(),
contextId);
}
//获取ContextID
private ContextId getContextId(ConfigurableApplicationContext applicationContext) {
//父容器获取spring.application.name对应的bean
ApplicationContext parent = applicationContext.getParent();
if (parent != null && parent.containsBean(ContextId.class.getName())) {
return parent.getBean(ContextId.class).createChildId();
}
//父容器获取不到,则生成一个contextId
return new ContextId(getApplicationId(applicationContext.getEnvironment()));
}
//获取应用ID
private String getApplicationId(ConfigurableEnvironment environment) {
//获取属性:spring.application.name
String name = environment.getProperty("spring.application.name");
//如果为空,默认名application
return StringUtils.hasText(name) ? name : "application";
}
//ContextId类
class ContextId {
//原子Long类
private final AtomicLong children = new AtomicLong(0);
private final String id;
ContextId(String id) {
this.id = id;
}
ContextId createChildId() {
//线程安全递增
return new ContextId(this.id + "-" + this.children.incrementAndGet());
}
String getId() {
return this.id;
}
}
}
4.4 ConfigurationWarningsApplicationContextInitializer
配置告警初始化器, 用于检测注解了包org, org.springframework包内的类, 如果注解了,那么打印warn日志
public class ConfigurationWarningsApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext context) {
//添加一个beanFactory后置处理器
//ConfigurationWarningsPostProcessor的子类
context.addBeanFactoryPostProcessor(
new ConfigurationWarningsPostProcessor(getChecks()));
}
//返回ComponentScanPackageCheck实例
protected Check[] getChecks() {
return new Check[] { new ComponentScanPackageCheck() };
}
/**
* 配置错误后置处理器
*/
protected static final class ConfigurationWarningsPostProcessor
implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {
private Check[] checks;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
//处理各个检查之后的警告
for (Check check : this.checks) {
//没有问题的话message为null
String message = check.getWarning(registry);
if (StringUtils.hasLength(message)) {
//有错误信息,打印告警信息
warn(message);
}
}
}
private void warn(String message) {
if (logger.isWarnEnabled()) {
//打印告警日志
logger.warn(String.format("%n%n** WARNING ** : %s%n%n", message));
}
}
}
//Component注解扫描Check类
protected static class ComponentScanPackageCheck implements Check {
//有问题的包
private static final Set<String> PROBLEM_PACKAGES;
static {
//将org和org.springframework包添加到PROBLEM_PACKAGES
//也就是不允许配置这两个包内的类方法和属性
Set<String> packages = new HashSet<>();
packages.add("org.springframework");
packages.add("org");
PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
}
@Override
public String getWarning(BeanDefinitionRegistry registry) {
//获取被扫描的包
Set<String> scannedPackages = getComponentScanningPackages(registry);
//获取有问题的包
List<String> problematicPackages = getProblematicPackages(scannedPackages);
if (problematicPackages.isEmpty()) {
//没有问题返回null
return null;
}
//有问题返回的错误信息
return "Your ApplicationContext is unlikely to "
+ "start due to a @ComponentScan of "
+ StringUtils.collectionToDelimitedString(problematicPackages, ", ")
+ ".";
}
private boolean isProblematicPackage(String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return true;
}
//如果包名为org或者org.springframework
//那么返回true,否则返回false
return PROBLEM_PACKAGES.contains(scannedPackage);
}
private String getDisplayName(String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return "the default package";
}
return "'" + scannedPackage + "'";
}
}
}
4.5 ServerPortInfoApplicationContextInitializer
服务端口初始化器, 分别实现了ApplicationContextInitializer和ApplicationListener接口, 在applicationContext中添加了事件监听器this, 监听了WebServerInitializedEvent事件, 配置服务的端口号
public class ServerPortInfoApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext>,
ApplicationListener<WebServerInitializedEvent> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//把this添加到Application的listener中
applicationContext.addApplicationListener(this);
}
//监听处理WebServerInitializedEvent事件
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
//获取environment中配置的server.ports
String propertyName = "local." + getName(event.getApplicationContext()) + ".port";
setPortProperty(event.getApplicationContext(), propertyName,
event.getWebServer().getPort());
}
}
4.6 ConditionEvaluationReportLoggingListener
条件评估日志监听器, 主要作用是给applicationContext添加了一个ConditionEvaluationReportListener监听器, ConditionEvaluationReportListener监听了ContextRefreshedEvent和ApplicationFailedEvent事件, 打印相应日志
public class ConditionEvaluationReportLoggingListener
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
//applicationContext中添加一个ConditionEvaluationReportListener
applicationContext
.addApplicationListener(new ConditionEvaluationReportListener());
if (applicationContext instanceof GenericApplicationContext) {
//注册一个ConditionEvaluationReport bean
this.report = ConditionEvaluationReport
.get(this.applicationContext.getBeanFactory());
}
}
//监听到ApplicationEvent
protected void onApplicationEvent(ApplicationEvent event) {
ConfigurableApplicationContext initializerApplicationContext = this.applicationContext;
if (event instanceof ContextRefreshedEvent) {
//ContextRefreshed事件
if (((ApplicationContextEvent) event)
.getApplicationContext() == initializerApplicationContext) {
logAutoConfigurationReport();
}
}
else if (event instanceof ApplicationFailedEvent
&& ((ApplicationFailedEvent) event)
.getApplicationContext() == initializerApplicationContext) {
//ApplicationFailedEvent事件
logAutoConfigurationReport(true);
}
}
}
//用于记录Condition注解的评估情况
public final class ConditionEvaluationReport {
//bean名称为autoConfigurationReport
//类型为ConditionEvaluationReport
private static final String BEAN_NAME = "autoConfigurationReport";
//从beanFactory中获取ConditionEvaluationReport实例
public static ConditionEvaluationReport get(
ConfigurableListableBeanFactory beanFactory) {
synchronized (beanFactory) {
ConditionEvaluationReport report;
if (beanFactory.containsSingleton(BEAN_NAME)) {
//如果bean已经被注册,立即返回
report = beanFactory.getBean(BEAN_NAME, ConditionEvaluationReport.class);
}
else {
//否则注册bean
report = new ConditionEvaluationReport();
beanFactory.registerSingleton(BEAN_NAME, report);
}
locateParent(beanFactory.getParentBeanFactory(), report);
return report;
}
}
}
5. 发布ApplicationContextInitializedEvent事件
Application容器初始化完成事件, 对该事件感兴趣的监听器有
- BackgroundPreinitializer
- DelegatingApplicationListener
BackgroundPreinitializer
扩展点, 后台进程初始化器, 用于多线程执行后台耗时任务, 在这里不处理ApplicationContextInitializedEvent事件
DelegatingApplicationListener
扩展点, 代理监听器, 继续分发事件, 不处理ApplicationContextInitializedEvent事件
6. 打印启动和profile日志
//logStartupInfo默认为true
if (this.logStartupInfo) {
//打印项目启动信息
// Starting YanggxApplication on pcname with PID 12372 (E:\java\spring\target\classes started by username in E:\java\spring)
logStartupInfo(context.getParent() == null);
//打印profile
//No active profile set, falling back to default profiles: default
logStartupProfileInfo(context);
}
7. 注册单例Bean
注册了两个单例Bean
- 命令行参数bean, 名称为springApplicationArguments, 值为applicationArgument
- banner bean, 名称为springBootBanner, 值为printedBanner
//注册命令行参数bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
//banner bean
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
7.1 手工注册单例Bean流程
调用DefaultListableBeanFactory#registerSingleton方法, 显示调用父类DefaultSingletonBeanRegistry#registerSingleton方法
DefaultListableBeanFactory 手工注册单例Bean
手工注册单例Bean, 不同于扫描bean定义, 然后注册单例bean, 手工注册的单例Bean, 没有维护到beanDefinitionMap中, 而是将beanName维护到manualSingletonNames中
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
//注册单例bean
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
//判断bean的创建过程是否已经开始了
//调用抽象父类AbstractBeanFactory#hasBeanCreationStarted()方法
//判断AbstractBeanFactory成员变量alreadyCreated Set不为空
if (hasBeanCreationStarted()) {
//bean创建过程已经开始了
//锁住成员变量beanDefinitionMap
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
//如果bean定义Map, beanDefinitionMap已经包含了bean
//维护到手工单例bean名称manualSingletonNames中
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames.size() + 1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// bean还没有注册过, 仍处于启动注册阶段
if (!this.beanDefinitionMap.containsKey(beanName)) {
//如果beanDefinitionMap不包含beanName
//那么添加到manualSingletonNames
this.manualSingletonNames.add(beanName);
}
}
//清空allBeanNamesByType和singletonBeanNamesByType
clearByTypeCache();
}
}
DefaultSingletonBeanRegistry手工注册单例Bean
将beanName添加到registeredSingletons中, beanName和对应的对象保存singletonObjects中, 并删除beanName对应的beanFactory, earlySingleton
//默认单例bean注册器
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//缓存单例bean, key为bean名称,value为bean实例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//缓存beanFactory, key为bean名称, value为beanFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
//早期单例缓存, key为bean名称, value为bean实例
//为了解决循环依赖而引入的
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//单例bean名称set
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
//正在创建的单例bean名称set
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//手工注册单例bean
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
//判断名称和值不可以为空
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
synchronized (this.singletonObjects) {
//判断bean是否为空
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
//不为空抛异常
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
//添加一个单例bean
addSingleton(beanName, singletonObject);
}
}
//添加一个单例bean
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//保存到singletonObjects的map中
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
//添加beanName
this.registeredSingletons.add(beanName);
}
}
}
8. 初始化BeanDefinitionLoader, 加载Application
首先生成一个BeanDefinitionLoader, 用于加载SpringApplication的成员变量sources, 当前sources列表中只有YanggxApplication.class一个对象
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//实例化BeanDefinitionLoader
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
//this.beanNameGenerator为null
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
//this.resourceLoader为null
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
//this.environment为null
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
//调用load()方法,加载各个sources
loader.load();
}
8.1 BeanDefinitionLoader
加载SpringApplication维护的sources列表资源, 可以加载类, XML, groovy等资源, 由于我们传入的sources中只有一个YanggxApplication.class, 所以调用的是load(Class<?> source)方法, 最后调用的是AnnotatedBeanDefinitionReader#register()方法, 注册了一个Bean定义
class BeanDefinitionLoader {
//启动类列表
private final Object[] sources;
//注解Bean定义读取器
private final AnnotatedBeanDefinitionReader annotatedReader;
//XML Bean定义读取器
private final XmlBeanDefinitionReader xmlReader;
//groovy Bean定义读取器
private BeanDefinitionReader groovyReader;
//Bean定义扫描器
private final ClassPathBeanDefinitionScanner scanner;
//资源加载器
private ResourceLoader resourceLoader;
/**
* 构造函数
*/
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
//传入的sources, 目前只有YanggxApplication.class
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
//使用了groovy
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
this.scanner = new ClassPathBeanDefinitionScanner(registry);
//排除sources扫描
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
/**
* 加载sources
*/
public int load() {
int count = 0;
for (Object source : this.sources) {
count += load(source);
}
return count;
}
//加载Object资源
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) {
//加载Resource资源
return load((Resource) source);
}
if (source instanceof Package) {
//加载Package资源
return load((Package) source);
}
if (source instanceof CharSequence) {
//加载字符串资源
return load((CharSequence) source);
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
//加载类资源
private int load(Class<?> source) {
if (isGroovyPresent()
&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// 使用了groovy,加载groovy资源
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
GroovyBeanDefinitionSource.class);
load(loader);
}
//如果是@Component注解
if (isComponent(source)) {
this.annotatedReader.register(source);
return 1;
}
return 0;
}
//加载groovy资源
private int load(GroovyBeanDefinitionSource source) {
int before = this.xmlReader.getRegistry().getBeanDefinitionCount();
((GroovyBeanDefinitionReader) this.groovyReader).beans(source.getBeans());
int after = this.xmlReader.getRegistry().getBeanDefinitionCount();
return after - before;
}
//加载resource资源
private int load(Resource source) {
if (source.getFilename().endsWith(".groovy")) {
//使用了groovy
if (this.groovyReader == null) {
throw new BeanDefinitionStoreException(
"Cannot load Groovy beans without Groovy on classpath");
}
return this.groovyReader.loadBeanDefinitions(source);
}
//加载xml资源
return this.xmlReader.loadBeanDefinitions(source);
}
//加载package资源
private int load(Package source) {
//scanner扫描
return this.scanner.scan(source.getName());
}
//load xml资源
private int load(CharSequence source) {
String resolvedSource = this.xmlReader.getEnvironment()
.resolvePlaceholders(source.toString());
try {
//先尝试加载类资源
return load(ClassUtils.forName(resolvedSource, null));
}
catch (IllegalArgumentException | ClassNotFoundException ex) {
}
// 不成功的话,加载resource资源
Resource[] resources = findResources(resolvedSource);
int loadCount = 0;
boolean atLeastOneResourceExists = false;
for (Resource resource : resources) {
if (isLoadCandidate(resource)) {
atLeastOneResourceExists = true;
loadCount += load(resource);
}
}
if (atLeastOneResourceExists) {
return loadCount;
}
// 不成功的话,加载package资源
Package packageResource = findPackage(resolvedSource);
if (packageResource != null) {
return load(packageResource);
}
//还不成功的话,就抛异常
throw new IllegalArgumentException("Invalid source '" + resolvedSource + "'");
}
}
AnnotatedBeanDefinitionReader注册Bean定义
public class AnnotatedBeanDefinitionReader {
//Class列表注册Bean定义
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
//单个Bean注册
registerBean(annotatedClass);
}
}
//单个Class注册bean
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
//注册Bean定义
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//生成注解BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//判断是否符合@Conditional注解的条件
//不满足的话, 就不注册Bean
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//设置instanceSupplier, //AbstractAutowireCapableBeanFactory#createBeanInstance中调用了instanceSupplier.get()生成bean实例
abd.setInstanceSupplier(instanceSupplier);
//Scope元空间
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//生成Bean名称
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//处理Lazy, Primary, DependsOn, Role, Description注解
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));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
//beanDefinition定制器
customizer.customize(abd);
}
//bean定义容器
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//Scope代理模式处理
//ScopedProxyMode.DEFAULT和NO不需要代理处理
//INTERFACES使用JDK动态代理
//TARGET_CLASS使用CGLIB动态代理
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注册Bean定义
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
9. 发布contextLoaded事件
调用listeners.contextLoaded(context), 发布了一个ApplicationPreparedEvent事件, 对ApplicationPreparedEvent事件感兴趣的监听器有:
- ConfigFileApplicationListener
- LoggingApplicationListener
- BackgroundPreinitializer
- DelegatingApplicationListener
9.1 ConfigFileApplicationListener
配置文件监听器
public class ConfigFileApplicationListener
implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
//事件处理
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
//处理ApplicationPreparedEvent
onApplicationPreparedEvent(event);
}
}
//处理ApplicationPreparedEvent
private void onApplicationPreparedEvent(ApplicationEvent event) {
this.logger.switchTo(ConfigFileApplicationListener.class);
addPostProcessors(((ApplicationPreparedEvent) event).getApplicationContext());
}
//applicationContext中添加一个PropertySourceOrderingPostProcessor
protected void addPostProcessors(ConfigurableApplicationContext context) {
//用于重排序PropertySourceOrderingPostProcessor
context.addBeanFactoryPostProcessor(
new PropertySourceOrderingPostProcessor(context));
}
}
9.2 LoggingApplicationListener
日志监听器
public class LoggingApplicationListener implements GenericApplicationListener {
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
ConfigurableListableBeanFactory beanFactory = event.getApplicationContext()
.getBeanFactory();
//注册日志单例bean
if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
}
}
}
9.3 BackgroundPreinitializer
后台预初始化器, 当前不做任务处理, 方便以后扩展
9.4 DelegatingApplicationListener
代理监听器, 不做任何处理, 方便以后扩展
总结
这一步的主要作用是为下面刷新applicationContext做准备
- 统一了ApplicationContext和Application的environment
- 设置ApplicationContext的beanNameGenerator,resouceLoader和classLoader, 并设置beanFactory的类型转换Service
- 执行Initializer
- 发布ApplicationContextInitializedEvent
- 打印启动日志和profile日志
- 手工注册命令行和banner两个单例Bean
- 初始化BeanDefinitionLoader, 加载启动类sources
- 发布contextLoaded事件
下一篇
我们将会在下一篇refreshContext()刷新应用上下文, 研究springboot如何扫描加载bean, 如何建立webserver容器