概述
[spring的使用示例](https://github.com/siyuburno/spring-read-demo/tree/master/src/main/java/ioc/container/demo/beanlifecycle),spring的启动过程就是应用上下文的初始化过程。可通过如下方式创建一个AnnotationConfigApplicationContext的应用上下文对象:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("ioc.container.demo");
将执行下面的构造函数:
/**
* Create a new AnnotationConfigApplicationContext, scanning for components
* in the given packages, registering bean definitions for those components,
* and automatically refreshing the context.
* @param basePackages the packages to scan for component classes
*/
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
可以看到,启动过程分为3个部分:
- this()无参构造函数的执行
- 扫描BeanDefinition
- refresh()刷新应用上下文
解析
this()无参构造函数的执行
this()先执行父类GenericApplicationContext的无参构造函数: /**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
再执行AnnotationConfigApplicationContext的无参构造行数:
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
this()的整体整体逻辑是:
- 初始化DefaultListableBeanFactory作为IOC容器。
- 设置AnnotatedBeanDefinitionReader,可读取@Configuration标注类中的bean。
- 设置ClassPathBeanDefinitionScanner,可读取指定包中@Component定义的bean。
扫描BeanDefinition
当前情景下会使用ClassPathBeanDefinitionScanner对象来扫描BeanDefinition,最终执行: /**
* Perform a scan within the specified base packages,
* returning the registered bean definitions.
* <p>This method does <i>not</i> register an annotation config processor
* but rather leaves this up to the caller.
* @param basePackages the packages to check for annotated classes
* @return set of beans registered if any for tooling registration purposes (never {@code null})
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 1. 扫描文件作为Resource:读取指定包下所有的.java文件作为资源。
// 2. 将Resource解析成BeanDefinition:判断资源是否被@Component标注,如果是则解析资源。
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 将BeanDefinition注册到BeanFactory。
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
- 扫描文件作为Resource:读取指定包下所有的.java文件作为资源。
- 将Resource解析成BeanDefinition:判断资源是否被@Component标注,如果是则解析资源。
- 将BeanDefinition注册到Beanfactory。
refresh()刷新应用上下文
refresh()的逻辑定义在父类AbstractApplicationContext中: @Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 1 预备应用上下文
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 2.1 预备BeanFactory:设置refreshed=true,设置BeanFactory的id
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 2.2 预备BeanFactory:设置各种各样的BeanFactory的属性值
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 3 预处理BeanFactory,留给子类实现自定义逻辑
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 4 执行PostBeanFactoryProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 5 注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 6 初始化国际化(MassageSource)
initMessageSource();
// Initialize event multicaster for this context.
// 7 初始化应用事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 8 执行onRefresh方法,留给子类实现自定义逻辑
onRefresh();
// Check for listener beans and register them.
// 9 注册监听器,发布前置事件
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 10 注册所有非懒加载的bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 11 发布ContextRefreshedEvent事件。
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
- 预备应用上下文
- 初始化状态位人:closed=false、active=true;
- 创建Environment对象,校验其配置。
- 加载内置监听器(ApplicationListener)
- 初始化内置事件的列表(ApplicationEvent)
- 预备BeanFactory
- 设置refreshed=true,设置BeanFactory的id
- 设置各种各样的BeanFactory的属性值。
- 预处理BeanFactory,留给子类实现自定义逻辑
- 执行BeanFactoryPostProcessor
- 注册BeanPostProcessor
- 初始化国际化MessageSource
- 初始化应用事件广播器
- 执行onRefresh方法,留给子类实现自定义逻辑
- 注册监听器的bean,发布前置事件。
- 注册所有非懒加载的bean。
- 发布ContextRefreshedEvent事件。