springboot的启动过程是由一行SpringApplication.run开始的, 其所有的内部细节都隐藏在源码中, 今天一一为大家解开, 过程比较长, 耐心观看相信会有收获的
1. 容器启动
1.1 创建一个SpringApplication
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return new SpringApplication(primarySources).run(args);
}
1.2 开启SpringApplicatioin的run方法, 在这里完成了以下工作
- 创建监听器
- 触发监听器
- 创建上下文
- 加载BeanDefinition/BeanFactory/BeanPostProcess等等
- 调用ApplicationContextInitializer, 执行一些初始化代码
- 刷新上下文, 加载所有的bean实例
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//这里预留了一个空的上下文引用, 并没有真正创建
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//@1 这里添加了一下监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//@2 这里比较重要, 激活了ApplicationEnvironmenPreparedEvent的listener
//也就是从这一步开始, 转而去创建bootstrap的上下文
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//@3 创建了一个上下文
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//@4 准备上下文, 这里调用applyInitializers会触发ApplicationContextInitializer的
//初始化
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//@5 刷新上下文, 非常重要, 必看, 这里面加载了容器的所有类
refreshContext(context);
//预留入口, 空代码
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
//执行容器中的CommandLineRunner和ApplicationRunner, 默认为空
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
@1 创建Listener详解
a. getRunListeners方法, 内部调用getSpringFactoriesInstances
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
b.getSpringFactoriesInstances, 这里使用SpringFactoriesLoader的静态方法加载
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
c.进入SpringFactoriesLoader方法
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
.....
}
debug发现此时的cache已经有值了, 是什么时候加载进去的呢?
重新回到SpringApplicaton的构造方法, 在这里加载了比较重要的类
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
进去getSpringFactoriesInstances看一下, 这里其实是同一个方法, 也就是说在new SpringApplication的时候cache中设置了值, 后续直接从cache中取值
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
//初次运行, result为空
try {
Enumeration<URL> urls = (classLoader != null ?
//FACTORIES_RESOURCE_LOCATION就是"META-INF/spring.factories", 看到这里恍然大悟, 原来就是加载META-INF的启动类
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
//这里的url会指向spring-boot-2.1.4.RELEASE下的/META-INFO/spring.factories
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
//加载了8个主要的类, 见下图
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryClassName = ((String) entry.getKey()).trim();
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
//放入静态变量cache中
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
好了, 找到了cache的值来源, 我们回到@1开头的地方, 这时候已经加载了ApplicatonListener
@1的流程完成
@2 prepearEnvironment详解
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// @2.1创建environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
//@2.2给listener设置environment, 注意这里通知了BootstrapApplicationListener, 也就是会先去初始化BootStrap的加载
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
@2.1 创建environment
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
//走到这里, 创建了StandardServletEnvironment
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
这时候已经创建了environment, 而且是bootstrap的environment, 通过debug可以看出来.
所以这时候先暂停一下spring上下文的创建 , 去分析一下bootstrap的上下文, 以及那些配置文件是如何加载的,nacos配置是如何加载的, 和spring的上下文又是什么关系
@3 经过了上面的环境准备与bootstrap步骤, 接下来开始创建spring的上下文
context = createApplicationContext();
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
//本次是servlet, 会走到这里
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
//如果bootstrap会进入到这里, 创建Default上下文
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
注意这时候context刚刚创建,此时的parent为null, environment的值是spring环境刚刚创建的. 此时bootstrap的上下文及environment跑到哪里去了呢? 又是如何关联起来的?
@4 准备上下文prepareContext
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
//@4.1 这里加载了非常重要的
postProcessApplicationContext(context);
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
2.监听器启动
首先debug看一下, spring初始化的时候加载了哪些监听器呢?
从上图可以看到, 一共是13个监听器, 其中的第一个就是BootstrapApplicationListener
完整的看一下监听器的加载和调用过程:
SpringApplication.class
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
//调用监听器的环境准备
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
SpringApplicationRunListeners.class
public void environmentPrepared(ConfigurableEnvironment environment) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.environmentPrepared(environment);
}
}
EventPublishingRunListener.class
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
this.application, this.args, environment));
}
SimpleApplicationEventMulticaster.class
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
//随着代码逐行的跟进, 最终进入了这个方法, 这次关注的是BootstrapApplicationListener
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
BootstrapApplicationListener.class
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
//检查环境配置中是否存在名为spring.cloud.bootstrap.enabled的属性,如果属性不存在或值为false,则直接返回,不执行后续操作。
if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class,
true)) {
return;
}
//检查属性源中是否包含名为BOOTSTRAP_PROPERTY_SOURCE_NAME的属性源,如果包含,则直接返回,不执行后续操作。
if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
return;
}
ConfigurableApplicationContext context = null;
String configName = environment
.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
for (ApplicationContextInitializer<?> initializer : event.getSpringApplication()
.getInitializers()) {
if (initializer instanceof ParentContextApplicationContextInitializer) {
//如果当前初始化器是ParentContextApplicationContextInitializer类型,则调用findBootstrapContext方法查找引导上下文,并将结果存储在context变量中。
context = findBootstrapContext(
(ParentContextApplicationContextInitializer) initializer,
configName);
}
}
if (context == null) {
context = bootstrapServiceContext(environment, event.getSpringApplication(),
configName);
event.getSpringApplication()
.addListeners(new CloseContextOnFailureApplicationListener(context));
}
apply(context, event.getSpringApplication(), environment);
}
经过的分析, 我们看到了spring和springboot的关系, 以及两者是如何完美兼容的
3.bootstrap上下文
通过上面的文章, 我们已经知道Bootstrap的创建是由事件监听器触发的, 入口是onApplicationEvent, 所以我们从listener的入口开始, 循序渐进解开bootstrap的面纱
3.1 BootstrapApplicationListener.onApplicationEvent
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
//这一步得到已经创建好的environment,具体是哪一步呢, 请翻到@2.1
ConfigurableEnvironment environment = event.getEnvironment();
if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class,
true)) {
return;
}
// don't listen to events in a bootstrap context
if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
return;
}
ConfigurableApplicationContext context = null;
String configName = environment
.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
for (ApplicationContextInitializer<?> initializer : event.getSpringApplication()
.getInitializers()) {
//这里的for循环不会走到, initializer 没有这个类型
if (initializer instanceof ParentContextApplicationContextInitializer) {
context = findBootstrapContext(
(ParentContextApplicationContextInitializer) initializer,
configName);
}
}
if (context == null) {
//@1 context为null, 创建bootstrapServiceContext, 代码在下面贴出来了,标记为@2
context = bootstrapServiceContext(environment, event.getSpringApplication(),
configName);
event.getSpringApplication()
.addListeners(new CloseContextOnFailureApplicationListener(context));
}
@3 获取ApplicationContextInitializer并执行
apply(context, event.getSpringApplication(), environment);
}
//真正的创建上下文的地方
private ConfigurableApplicationContext bootstrapServiceContext(
ConfigurableEnvironment environment, final SpringApplication application,
String configName) {
//新建了一个bootstrap的environment
StandardEnvironment bootstrapEnvironment = new StandardEnvironment();
MutablePropertySources bootstrapProperties = bootstrapEnvironment
.getPropertySources();
//移除了bootstrapProperties里的所有内容
for (PropertySource<?> source : bootstrapProperties) {
bootstrapProperties.remove(source.getName());
}
String configLocation = environment
.resolvePlaceholders("${spring.cloud.bootstrap.location:}");
String configAdditionalLocation = environment
.resolvePlaceholders("${spring.cloud.bootstrap.additional-location:}");
Map<String, Object> bootstrapMap = new HashMap<>();
//这里的configName是"bootstrap"
bootstrapMap.put("spring.config.name", configName);
bootstrapMap.put("spring.main.web-application-type", "none");
if (StringUtils.hasText(configLocation)) {
bootstrapMap.put("spring.config.location", configLocation);
}
if (StringUtils.hasText(configAdditionalLocation)) {
bootstrapMap.put("spring.config.additional-location",
configAdditionalLocation);
}
bootstrapProperties.addFirst(
new MapPropertySource(BOOTSTRAP_PROPERTY_SOURCE_NAME, bootstrapMap));
for (PropertySource<?> source : environment.getPropertySources()) {
if (source instanceof StubPropertySource) {
continue;
}
//这里塞入了systemProperties与systemEnvironment与bootstrap
bootstrapProperties.addLast(source);
}
//创建了一个Builder, 用于构建一个新的SpringApplication
SpringApplicationBuilder builder = new SpringApplicationBuilder()
.profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF)
.environment(bootstrapEnvironment)
.registerShutdownHook(false).logStartupInfo(false)
.web(WebApplicationType.NONE);
final SpringApplication builderApplication = builder.application();
if (builderApplication.getMainApplicationClass() == null) {
//没有执行
builder.main(application.getMainApplicationClass());
}
if (environment.getPropertySources().contains("refreshArgs")) {
//没有执行
builderApplication
.setListeners(filterListeners(builderApplication.getListeners()));
}
//又是一个重要的地方, 这里指定了bootstrap自动装配配置文件
builder.sources(BootstrapImportSelectorConfiguration.class);
//@2真正的创建上下文, run方法内部其实就是执行了SpringApplication的run
final ConfigurableApplicationContext context = builder.run();
context.setId("bootstrap");
// Make the bootstrap context a parent of the app context
addAncestorInitializer(application, context);
bootstrapProperties.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);
mergeDefaultProperties(environment.getPropertySources(), bootstrapProperties);
return context;
}
@1 在onApplicationEvent方法中, 调用bootstrapServiceContext创建上下文
@2 真正的创建上下文, 内部会再次走到SpringApplication.run, 加载并刷新上下文
@3 执行bootstrap上下文的initializers
这里有两个initializer, 其中PropertySourceBootstrapConfiguration就是本次的主角, 下面会展开讲解, 其是spring-cloud-context中的类, 也是通过它加载到nacos的bootstrap文件
接下来, 将再次回到SpringApplication的创建工程. 可以看到spring的加载过程非常非常的长, 能看到这里已经是一种胜利
回顾一下
main -> SpringApplication创建 -> spring启动事件开启 -> boostrap listener触发 -> bootsrap上下创建 -> 再次创建SpringApplication -> 刷新bootstrap上下文 -> bootstrap上下文加载完成, 加载了bootstrap部分类 -> 继续创建spring上下文, 以boostrap上下文作为父上下文 -> 加载其余的类
这样整理一下是不是清晰多了~
但是springApplication的上下文过程还没有讲解, 接下来是一块硬骨头, 啃下来就可以摸清spring容器是怎么玩转的了
遗留的一些问题:
- bootstrapContext与普通的springContext是什么时候建立联系的
- springcloud的配置文件是何时加载的
- spring的事件监听器是怎么玩的
4.spring上下文加载
主要分为以下步骤讲解
-
prepareContext - postProcessApplicationContext
- applyInitializers
- listeners.contextPrepared
- getBeanFactory
- createBeanDefinitionLoader
- listeners.contextLoaded
-
refreshContext - prepareRefresh Spring应用上下文启动准备阶段 - obtainFreshBeanFactory BeanFactory创建阶段 - prepareBeanFactory BeanFactory准备阶段 - postProcessBeanFactory BeanFactory后置处理阶段 - invokeBeanFactoryPostProcessors BeanFactory注册BeanPostProcessor阶段 - registerBeanPostProcessors 注册BeanPostProcessor - initMessageSource 初始化内建Bean:MessageSource - initApplicationEventMulticaster 初始化内建Bean:Spring事件广播器 - onRefresh Spring应用上下文刷新阶段,由子类实现 - registerListeners Spring事件监听器注册阶段 - finishBeanFactoryInitialization 实例化所有剩余的(非lazy init)单例 - finishRefresh 刷新完成阶段
-
afterRefresh
4.1 prepareContext
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//将ConfigurableEnvironment设置到ConfigurableApplicationContext中,用于配置应用程序的环境。
context.setEnvironment(environment);
//@1上下文后置处理器
postProcessApplicationContext(context);
//@2调用ApplicationContextInitializer初始化
applyInitializers(context);
//@3通知SpringApplicationRunListeners实例,应用程序上下文已准备就绪。
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//向应用程序上下文的bean工厂注册名为springApplicationArguments的单例bean,用于存储应用程序的参数。
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
//如果bean工厂是DefaultListableBeanFactory的实例,则设置是否允许覆盖bean定义。
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//@5获取所有应用程序的源,通常是用于启动Spring Boot应用程序的类。
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//@6加载应用程序的源到应用程序上下文中。
load(context, sources.toArray(new Object[0]));
//通知SpringApplicationRunListeners实例,应用程序上下文已加载完成。
listeners.contextLoaded(context);
}
@2 看一下Initiallizer都有哪些
@3通知SpringApplicationRunListeners实例,后续可以结合实际讲解spring中的事件节使用, spring也封装的很好, 开箱即用, 这里简单看一下有哪些事件节监听
@ 5 加载源, 当springboot项目刚启用时, 这里的source只有一个, 那就是org.springframework.cloud.bootstrap.BootstrapImportSelectorConfiguration
, 根据名字我们可以猜测到, springboot的很多启动类是从这里被载入的
这里可以再看一下第二次加载到的时候, 就变成了Main类
@6随着第五步完成, 这里开始加载BootstrapImportSelectorConfiguration
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//这里的context也是BeanDefinitionLoader , 所以此处的loader=context
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
//为加载器配置环境
loader.setEnvironment(this.environment);
}
进入BeanDefinitionLoader加载
loader.load();
}
BeanDefinitionLoader.class
private int load(Class<?> source) {
if (isGroovyPresent()
&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
GroovyBeanDefinitionSource.class);
load(loader);
}
if (isComponent(source)) {
//进入这里, 通过AnnotatedBeanDefinitionReader加载
this.annotatedReader.register(source);
return 1;
}
return 0;
}
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;
}
AnnotatedBeanDefinitionReader.class
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
//进入下一步
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
//进入下一步
doRegisterBean(annotatedClass, null, null, null);
}
//注册bootstrapImportSelectorConfiguration
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
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));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//工具类加载, 这里的进入真正的加载
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
到此, 又进入了spring的核心区别, BeanDefinition的加载和装配, 这一章不深入展开, 以后再单独讲解Bean容器是如何装载各个bean的