allSources = new LinkedHashSet<>();
if (!CollectionUtils.isEmpty(this.primarySources)) {
allSources.addAll(this.primarySources);
}
if (!CollectionUtils.isEmpty(this.sources)) {
allSources.addAll(this.sources);
}
return Collections.unmodifiableSet(allSources);
}
getAllSource
load() 主要将主启动类生成实例对象保存在容器中,spring容器在启动的时候会将类解析成spring内部的BeanDefinition结构,并将BeanDefinition存储到DefaultListableBeanFactory的map中。
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// 创建 BeanDefinitionLoader
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);
}
// 将启动类生成实例对象保存到容器中
loader.load();
}
getBeanDefinitionRegistry(context) 将上下文转换为 BeanDefinitionRegistry 类型
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
if (context instanceof BeanDefinitionRegistry) {
return (BeanDefinitionRegistry) context;
}
if (context instanceof AbstractApplicationContext) {
return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory();
}
throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
}
getBeanDefinitionRegistry
getBeanDefinitionRegistry
createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources) 创建BeanDefinitionLoader,其中创建一些Bean定义读取器。
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;
// 创建注解形式的Bean定义读取器, eg:@Configuration @Bean @Component @Controller 等
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
// 创建xml形式的Bean定义读取器
this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
// 创建类路径扫描器
this.scanner = new ClassPathBeanDefinitionScanner(registry);
// 扫描器添加排除过滤器
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
loader.load()将启动类生成实例对象保存在容器中。
void load() {
for (Object source : this.sources) {
//source 为启动类
load(source);
}
}
private void load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class) {
// 从class中加载
load((Class) source);
return;
}
if (source instanceof Resource) {
// 从 Resource 中加载
load((Resource) source);
return;
}
if (source instanceof Package) {
// 从 Package 中加载
load((Package) source);
return;
}
if (source instanceof CharSequence) {
// 从 CharSequence 中加载
load((CharSequence) source);
return;
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
private void 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);
((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());
}
if (isEligible(source)) {
// 将启动类的 BeanDefinition 注册到 BeanDefinitionMap 中
this.annotatedReader.register(source);
}
}
load()
load
2.5 刷新上下文
主要逻辑为AbstractApplicationContext 对象的 refresh() 方法,进行整个容器的刷新过程,会调用spring中的refresh()方法,其中有13个关键方法,来完成整个
SpringBoot应用程序的启动。
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
shutdownHook.registerApplicationContext(context);
}
refresh(context);
}
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
prepareRefresh() ;
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() ;
prepareBeanFactory(beanFactory ) ;
try {
postProcessBeanFactory(beanFactory ) ;
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process" );
invokeBeanFactoryPostProcessors(beanFactory ) ;
registerBeanPostProcessors(beanFactory ) ;
beanPostProcess.end () ;
initMessageSource() ;
initApplicationEventMulticaster() ;
onRefresh() ;
registerListeners() ;
finishBeanFactoryInitialization(beanFactory ) ;
finishRefresh() ;
}
catch (BeansException ex) {
if (logger.isWarnEnabled() ) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans() ;
cancelRefresh(ex ) ;
throw ex;
}
finally {
resetCommonCaches() ;
contextRefresh.end () ;
}
}
复制
}
invokeBeanFactoryPostProcessors(beanFactory) 改方法会解析核心启动类中 @SpringBootApplication 实现自动配置
Ioc容器的初始化包括三个步骤,该三个步骤在 invokeBeanFactoryPostProcessors 中完成
1、Resource定位
在SpringBoot中,包扫描是从主类所在包开始扫描,prepareContext()方法中,会将主类解析成BeanDefinition保存在容器中,然后在refresh()方法的invokeBeanFactoryPostProcessors()方法中解析主类的BeanDefinition获取basePackage的路径。这样就完成了定位的过程。
SpringBoot的各种starter是通过SPI扩展机制实现的自动装配,SpringBoot的自动装配同样也是在invokeBeanFactoryPostProcessors()方法中实现的。 在SpringBoot中有很多的@EnableXXX注解,其底层是@Import注解,在invokeBeanFactoryPostProcessors()方法中也实现了对该注解指定的配置类的定位加载。
常规在SpringBoot中有三种定位方法:主类所在的包、SPI扩展机制实现的自动装配、@Import注解指定的类
SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类,也可以这样理解:SPI是“基于接口的编程+策略模式+配置文件”组成实现的动态加载机制。
2、BeanDefinition的载入
SpringBoot会将通过定位得到的basePackage的路径拼装成 classpath:com/***/.class 的形式,然后 PathMatchingResourcePatternResolver类会将该路径下所有的 .class 文件加载进来,然后进行遍历判断是否含有 @Component 注解,如果有就是要装载的 BeanDefinition。
3、注册Beanfinition
注册过程是将载入过程中解析得到的BeanDefinition向IOC容器进行注册。通过上下文分析,在容器中将BeanDefinition注入到一个ConcurrenHashMap中,IOC容器通过这个map来保存BeanDefinition数据。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (!NativeDetector .in NativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD\_TIME \_WEAVER \_BEAN \_NAME ) ) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory ) );
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory .getBeanClassLoader () ));
}
复制
}
// PostProcessorRegistrationDelegate
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>() ;
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>() ;
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>() ;
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry ) ;
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>() ;
String\[\] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class , true , false ) ;
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName , PriorityOrdered.class ) ) {
currentRegistryProcessors.add(beanFactory.getBean(ppName , BeanDefinitionRegistryPostProcessor.class ) );
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors , beanFactory ) ;
registryProcessors.addAll(currentRegistryProcessors ) ;
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors , registry , beanFactory .getApplicationStartup () );
currentRegistryProcessors.clear() ;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class , true , false ) ;
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName , Ordered.class ) ) {
currentRegistryProcessors.add(beanFactory.getBean(ppName , BeanDefinitionRegistryPostProcessor.class ) );
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors , beanFactory ) ;
registryProcessors.addAll(currentRegistryProcessors ) ;
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors , registry , beanFactory .getApplicationStartup () );
currentRegistryProcessors.clear() ;
boolean reiterate = true ;
while (reiterate) {
reiterate = false ;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class , true , false ) ;
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName , BeanDefinitionRegistryPostProcessor.class ) );
processedBeans.add(ppName);
reiterate = true ;
}
}
sortPostProcessors(currentRegistryProcessors , beanFactory ) ;
registryProcessors.addAll(currentRegistryProcessors ) ;
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors , registry , beanFactory .getApplicationStartup () );
currentRegistryProcessors.clear() ;
}
invokeBeanFactoryPostProcessors(registryProcessors , beanFactory ) ;
invokeBeanFactoryPostProcessors(regularPostProcessors , beanFactory ) ;
}
else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors , beanFactory ) ;
}
String\[\] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class , true , false ) ;
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>() ;
List<String> orderedPostProcessorNames = new ArrayList<>() ;
List<String> nonOrderedPostProcessorNames = new ArrayList<>() ;
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
}
else if (beanFactory.isTypeMatch(ppName , PriorityOrdered.class ) ) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName , BeanFactoryPostProcessor.class ) );
}
else if (beanFactory.isTypeMatch(ppName , Ordered.class ) ) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors , beanFactory ) ;
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors , beanFactory ) ;
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size() );
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName , BeanFactoryPostProcessor.class ) );
}
sortPostProcessors(orderedPostProcessors , beanFactory ) ;
invokeBeanFactoryPostProcessors(orderedPostProcessors , beanFactory ) ;
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size() );
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName , BeanFactoryPostProcessor.class ) );
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors , beanFactory ) ;
beanFactory.clearMetadataCache() ;
复制
}
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process" )
.tag("postProcessor" , postProcessor::toString);
postProcessor.postProcessBeanDefinitionRegistry(registry ) ;
postProcessBeanDefRegistry.end () ;
}
复制
}
invokeBeanFactoryPostProcessors
实现自动装配:
invokeBeanFactoryPostProcessors()方法主要是对 ConfigurationClassPostProcessor 类的处理,这是BeanDefinitionRegistryPostProcessor的子类,BeanDefinitionRegistryPostProcessor 是BeanDefinitionRegistryPostProcessor 的子类,调用BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry()方法,会解析 @PropertySource @ComponentScans @ComponentScan @Bean @Import 等注解
refresh() -> AbstractApplicationContext.invokeBeanFactoryPostProcessors(beanFactory)
-> invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup())
-> postProcessor.postProcessBeanDefinitionRegistry(registry) (ConfigurationClassPostProcessor类下的方法)
-> processConfigBeanDefinitions(registry) -> new ConfigurationClassParser() (解析@Configuration 标注的类)
-> parser.parse(candidates) (解析启动类上的注解)
-> this.reader.loadBeanDefinitions(configClasses) (生效自动配置类)
// ConfigurationClassPostProcessor
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry ) ;
复制
}
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION\_CLASS\_ATTRIBUTE) != null ) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this .metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
}) ;
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null ;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry ;
if (!this .localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr .getSingleton (
AnnotationConfigUtils.CONFIGURATION\_BEAN\_NAME\_GENERATOR);
if (generator != null ) {
this .componentScanBeanNameGenerator = generator;
this .importBeanNameGenerator = generator;
}
}
}
if (this .environment == null ) {
this .environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// 获取所有bean的全路径(解析各类注解)
parser.parse(candidates);
parser.validate();
Set <ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 使自动配置类生效
this .reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount" , () -> String .valueOf(configClasses.size())).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String \[\] newCandidateNames = registry.getBeanDefinitionNames();
Set <String > oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set <String > alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this .metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT\_REGISTRY\_BEAN\_NAME)) {
sbr.registerSingleton(IMPORT\_REGISTRY\_BEAN\_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no -op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
复制
}
postProcessBeanDefinitionRegistry
parser.parse(candidates) 从启动类开始解析各种注解(@PropertySource @ComponentScan @Import @ImportResource @Bean ),加载配置类,在processImports(configClass, sourceClass, getImports(sourceClass), filter, true)中对启动类进行解析,加载其中的@Import注解的类
public void parse(Set configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this .deferredImportSelectorHandler.process ();
复制
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate filter) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported() ) {
if (existingClass.isImported() ) {
existingClass.mergeImportedBy(configClass ) ;
}
return;
}
else {
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values() .removeIf(configClass ::equals ) ;
}
}
SourceClass sourceClass = as SourceClass(configClass , filter ) ;
do {
sourceClass = do ProcessConfigurationClass(configClass , sourceClass , filter ) ;
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
复制
}
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class .getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter );
}
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class ,
org.springframework.context.annotation.PropertySource.class )) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info ("Ignoring @PropertySource annotation on \[" + sourceClass.getMetadata().getClassName() +
"\]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
// 对启动类下的所有 @ComponentScan 进行解析加载,包含(@RestController @Service等)
Set <AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class , ComponentScan.class );
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER\_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set <BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null ) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter , true );
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class );
if (importResource != null ) {
String\[\] resources = importResource.getStringArray("locations");
Class <? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
Set <MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found , return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null ;
复制
}
parse
通过getImport(sourceClass) 解析启动类上的注解,获取到其中被@Import注解的类,即AutoConfigurationPackages、AutoConfigurationImportSelector
启动类上@SpringBootApplication注解为组合注解
@SpringBootConfiguration :其实质是一个 @Configuration 注解,表明该类是一个配置类
@EnableAutoConfiguration :开启了自动配置功能
@AutoConfigurationPackage :被该注解标注的类即主配置类,将主配置类所在的包当作base-package
@ComponentScan :直接向容器中注入指定的组件
在解析@Import注解时,会有一个getImports()方法,从启动类开始递归解析注解,把所有包含@Import的注解都解析到,然后再processImport()方法中对@Import注解的类进行分类,此处主要识别的是AutoConfigurationImportSelector 归属于ImportSelector的子类,在后续的过程中会调用 DeferredImprotSelectorHandler中的process()方法,来完成EnableAutoConfiguration的加载。
private Set getImports(SourceClass sourceClass) throws IOException {
Set imports = new LinkedHashSet<>();
Set visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
private void collectImports(SourceClass sourceClass, Set imports, Set visited)
throws IOException {
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations() ) {
String annName = annotation.getMetadata() .getClassName() ;
if (!annName.equals(Import .class .getName() )) {
collectImports(annotation , imports , visited ) ;
}
}
imports.addAll(sourceClass .getAnnotationAttributes (Import.class .getName () , "value" ));
}
复制
}
getImports
执行this.deferredImportSelectorHandler.process()方法进行实现自动装配
public void process() {
List deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
// ConfigurationClassParser
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate exclusionFilter = grouping.getCandidateFilter();
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
// 处理配置类上的注解
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
// DeferredImportSelectorGrouping
public Iterable getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
// 遍历DeferredImportSelectorHolder对象集合deferredImports,deferrdImports集合装了各种ImportSelector(AutoConfigurationImportSelect)
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
// 经过上面处理,然后再进行选择导入哪写配置类
return this.group.selectImports();
}
//AutoConfigurationImportSelector
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
// 获取自动配置类放入 AutoConfigurationEntry 对象中
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
// 将封装了自动配置类的 AutoConfigurationEntry 对象装进 autoConfigurationEntries 集合
this.autoConfigurationEntries.add(autoConfigurationEntry);
// 遍历刚获取的自动配置类
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
// 将符合条件的自动配置类作为 key,annotationMetadata作为值放进 entries 集合中
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
// AutoConfigurationImportSelector
public Iterable selectImports() {
if (this.autoConfigurationEntries.isEmpty()) {
return Collections.emptyList();
}
.getAutoConfigurationEntry(annotationMetadata);
// 得到所有要排除的自动配置类集合
Set allExclusions = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
.getAutoConfigurationEntry(annotationMetadata);
// 得到经过过滤后所有符合条件的自动配置类集合
Set processedConfigurations = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
.getAutoConfigurationEntry(annotationMetadata);
// 移除需要排除的自动配置类
processedConfigurations.removeAll(allExclusions);
.getAutoConfigurationEntry(annotationMetadata ) ;
return sortAutoConfigurations(processedConfigurations , getAutoConfigurationMetadata () ).stream()
.map((importClassName) -> new Entry(this .entries .get (importClassName ) , importClassName))
.collect(Collectors .to List() );
复制
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection importCandidates, Predicate exclusionFilter,
boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return ;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this .problemReporter.error(new CircularImportProblem(configClass, this .importStack));
}
else {
this .importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class )) {
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class ,
this .environment, this .resourceLoader, this .registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null ) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
this .deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
String\[\] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false );
}
}
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class )) {
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class ,
this .environment, this .resourceLoader, this .registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
this .importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class \[" +
configClass.getMetadata().getClassName() + "\]" , ex);
}
finally {
this .importStack.pop();
}
}
复制
}
执行 this.reader.loadBeanDefinitions(configClasses) 对自动配置类进行生效,生成Bean对象。
自动装配原理总结:
1、当启动SpringBoot应用程序时,会创建 SpringApplication 对象,在对象的构造方法中进行某些参数的初始化工作,最主要的是判断当前应用程序的类型及初始化器和监听器,在这个过程中会加载整个应用程序的 META-INF/spring.factories 文件,将文件的内容保存到缓存中(Map>> cache ),方便后续获取。
2、SpringApplication对象创建完成后,开始执行run() 方法来完成整个启动。启动过程中最主要的是有两个方法:prepareContext()、refreshContext(),在这两个方法中完成了自动装配的核心功能。在其之前的处理逻辑中包含了上下文对象的创建,banner的打印等各个准备工作。
3、在prepareContext()方法中主要完成的是对上下文对象的初始化操作,包含了属性值的设置(比如环境对象)。在整个过程中load()方法完成将当前启动类作为一个BeanDefinition注册到registry中,方便后续在进行BeanFactory调用执行时找到对应的主类,来完成对 @SpringBootApplication @EnableAutoConfiguration 等注解的解析工作。
4、在refreshContext()方法中会进行整个容器的刷新过程,会调用spring中的refresh()方法。refresh()中有13个关键方法,在自动装配过程中,会调用invokeBeanFactoryPostProcessors()方法主要是对 ConfigurationClassPostProcessor 类的处理,这是BeanDefinitionRegistryPostProcessor的子类,BeanDefinitionRegistryPostProcessor 是BeanDefinitionRegistryPostProcessor 的子类,调用BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry()方法,会解析@PropertySource @ComponentScans @ComponentScan @Bean @Import 等注解。
5、在解析@Import注解时,会有一个getImports()方法,从启动类开始递归解析注解,把所有包含@Import的注解都解析到,然后再processImport()方法中对@Import注解的类进行分类,此处主要识别的是AutoConfigurationImportSelector 归属于ImportSelector的子类,在后续的过程中会调用 DeferredImprotSelectorHandler中的process()方法,来完成EnableAutoConfiguration的加载。