详解springboot 自动装配原理

其实很多小伙伴都了解springboot的启动过程,其实在面试过程中问的最多的可能是自动装配的原理,而自动装配是在启动过程中完成,下面我就以流水账的形式带大家了解下自动装配的过程。

1、在springboot的启动过程中,有一个步骤是创建上下文,如果不记得可以看下面的代码:

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);
refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context); 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);
2、在prepareContext方法中查找load方法,一层一层向内点击,找到最终的load方法
}
    return context;
}

2、在prepareContext方法中查找load方法,一层一层向内点击,找到最终的load方法

//prepareContext方法
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment,
            SpringApplicationRunListeners listeners, ApplicationArguments
applicationArguments, Banner printedBanner) { context.setEnvironment(environment); 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); }
if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new
LazyInitializationBeanFactoryPostProcessor());
        }
        // Load the sources
        Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources //load方法完成该功能
load(context, sources.toArray(new listeners.contextLoaded(context);
}
must not be empty");
Object[0]));
/**
* Load beans into the application context.
* @param context the context to load beans into * @param sources the sources to load
* 加载bean对象到context中
*/
protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//获取bean对象定义的加载器
3、实际执行load的是BeanDefinitionLoader中的load方法,如下:
//实际记载bean的方法
private int load(Object source) {
Assert.notNull(source, "Source must not be null"); //如果是class类型,启用注解类型
if (source instanceof Class<?>) {
            return load((Class<?>) source);
        }
//如果是resource类型,启动xml解析
if (source instanceof Resource) {
            return load((Resource) source);
        }
//如果是package类型,启用扫描包,例如@ComponentScan if (source instanceof Package) {
            return load((Package) source);
        }
//如果是字符串类型,直接加载
if (source instanceof CharSequence) {
            return load((CharSequence) source);
        }
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
4、下面方法将用来判断是否资源的类型,是使用groovy加载还是使用注解的方式
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(); }
/**
* Load the sources into the reader. * @return the number of loaded beans */
    int load() {
        int count = 0;
for (Object source : this.sources) { count += load(source);
}
        return count;
    }

3、实际执行load的是BeanDefinitionLoader中的load方法,如下:

//实际记载bean的方法
private int load(Object source) {
Assert.notNull(source, "Source must not be null"); //如果是class类型,启用注解类型
if (source instanceof Class<?>) {
            return load((Class<?>) source);
        }
//如果是resource类型,启动xml解析
if (source instanceof Resource) {
            return load((Resource) source);
        }
//如果是package类型,启用扫描包,例如@ComponentScan if (source instanceof Package) {
            return load((Package) source);
        }
//如果是字符串类型,直接加载
if (source instanceof CharSequence) {
            return load((CharSequence) source);
        }
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}

4、下面方法将用来判断是否资源的类型,是使用groovy加载还是使用注解的方式

private int load(Class<?> source) { //判断使用groovy脚本
if (isGroovyPresent() &&
GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
5、下面方法判断启动类中是否包含@Component注解,但是会神奇的发现我们的启动类中并没有该注 解,继续更进发现MergedAnnotations类传入了一个参数SearchStrategy.TYPE_HIERARCHY,会查 找继承关系中是否包含这个注解,@SpringBootApplication-->@SpringBootConfiguration-- >@Configuration-->@Component,当找到@Component注解之后,会把该对象注册到 AnnotatedBeanDefinitionReader对象中
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
            load(loader);
        }
//使用注解加载
if (isComponent(source)) {
this.annotatedReader.register(source);
return 1; }
return 0; }

5、下面方法判断启动类中是否包含@Component注解,但是会神奇的发现我们的启动类中并没有该注 解,继续更进发现MergedAnnotations类传入了一个参数SearchStrategy.TYPE_HIERARCHY,会查 找继承关系中是否包含这个注解,@SpringBootApplication–>@SpringBootConfiguration-- >@Configuration–>@Component,当找到@Component注解之后,会把该对象注册到 AnnotatedBeanDefinitionReader对象中

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 (MergedAnnotations.from(type,
SearchStrategy.TYPE_HIERARCHY).isPresent(Component.class)) { return true;
}
// Nested anonymous classes are not eligible for registration, nor are groovy // closures
return !type.getName().matches(".*\\$_.*closure.*") &&
!type.isAnonymousClass()
&& type.getConstructors() != null && type.getConstructors().length !=
0; }
Supplier<T> supplier,
            @Nullable BeanDefinitionCustomizer[] customizers) {
        AnnotatedGenericBeanDefinition abd = new
AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
/**
* Register a bean from the given bean class, deriving its metadata from * class-declared annotations.
* 从给定的bean class中注册一个bean对象,从注解中找到相关的元数据
*/
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, @Nullable
 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)); }
} }
        if (customizers != null) {
            for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd); }
}
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd,
beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
/**
* Register the given bean definition with the given bean factory. * 注册主类,如果有别名可以设置别名
*/
    public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry
registry)
            throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases(); if (aliases != null) {
for (String alias : aliases) { registry.registerAlias(beanName, alias);
} }
}
//@SpringBootApplication
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented
@Inherited @SpringBootConfiguration
 
当看完上述代码之后,只是完成了启动对象的注入,自动装配还没有开始,下面开始进入到自动装配。
6、自动装配入口,从刷新容器开始
@Override
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
            prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory =
obtainFreshBeanFactory();
subclasses.
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context
    postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context. // 此处是自动装配的入口 invokeBeanFactoryPostProcessors(beanFactory);
}
7、在invokeBeanFactoryPostProcessors方法中完成bean的实例化和执行
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}
//@SpringBootConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented
@Configuration
public @interface SpringBootConfiguration {}
//@Configuration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented
@Component
public @interface Configuration {}

6、自动装配入口,从刷新容器开始

@Override
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
            prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory =
obtainFreshBeanFactory();
subclasses.
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context
    postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context. // 此处是自动装配的入口 invokeBeanFactoryPostProcessors(beanFactory);
}

7、在invokeBeanFactoryPostProcessors方法中完成bean的实例化和执行

/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans, * respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
    protected void
invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
8、查看invokeBeanFactoryPostProcessors的具体执行方法
//开始执行beanFactoryPostProcessor对应实现类,需要知道的是 beanFactoryPostProcessor是spring的扩展接口,在刷新容器之前,该接口可以用来修改bean元数据 信息
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
        // Detect a LoadTimeWeaver and prepare for weaving, if found in the
meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   } 
}

8、查看invokeBeanFactoryPostProcessors的具体执行方法

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory,
List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)
beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new
ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new
ArrayList<>(); //开始遍历三个内部类,如果属于BeanDefinitionRegistryPostProcessor子类,加
入到bean注册的集合,否则加入到regularPostProcessors
for (BeanFactoryPostProcessor postProcessor :
beanFactoryPostProcessors) {
                if (postProcessor instanceof
BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor);
beans them!
} else {
regularPostProcessors.add(postProcessor); }
}
// Do not initialize FactoryBeans here: We need to leave all regular // uninitialized to let the bean factory post-processors apply to
 implement
// Separate between BeanDefinitionRegistryPostProcessors that
// PriorityOrdered, Ordered, and the rest.
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors
= new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
//通过BeanDefinitionRegistryPostProcessor获取到对应的处理 类“org.springframework.context.annotation.internalConfigurationAnnotationProcess or”,但是需要注意的是这个类在springboot中搜索不到,这个类的完全限定名在 AnnotationConfigEmbeddedWebApplicationContext中,在进行初始化的时候会装配几个类,在创建 AnnotatedBeanDefinitionReader对象的时候会将该类注册到bean对象中,此处可以看到 internalConfigurationAnnotationProcessor为bean名称,容器中真正的类是 ConfigurationClassPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true,
false);
//首先执行类型为PriorityOrdered的BeanDefinitionRegistryPostProcessor //PriorityOrdered类型表明为优先执行
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //获取对应的bean
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//用来存储已经执行过的BeanDefinitionRegistryPostProcessor
processedBeans.add(ppName); }
}
sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); //开始执行装配逻辑
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
//其次执行类型为Ordered的BeanDefinitionRegistryPostProcessor //Ordered表明按顺序执行
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); currentRegistryProcessors.clear();
 
 // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
//循环中执行类型不为PriorityOrdered,Ordered类型的 BeanDefinitionRegistryPostProcessor
            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); currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//执行父类方法,优先执行注册处理类 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); //执行有规则处理类 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors,
beanFactory);
        }
beans
// Do not initialize FactoryBeans here: We need to leave all regular
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class,
true, false);
        // Separate between BeanFactoryPostProcessors that implement
PriorityOrdered,
// Ordered, and the rest.
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new
ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
 
9、开始执行自动配置逻辑(启动类指定的配置,非默认配置),可以通过debug的方式一层层向里进 行查找,会发现最终会在ConfigurationClassParser类中,此类是所有配置类的解析类,所有的解析逻 辑在parser.parse(candidates)中
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); }
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors,
beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<> (orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName,
BeanFactoryPostProcessor.class)); }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName,
BeanFactoryPostProcessor.class)); }
have
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache(); }

9、开始执行自动配置逻辑(启动类指定的配置,非默认配置),可以通过debug的方式一层层向里进 行查找,会发现最终会在ConfigurationClassParser类中,此类是所有配置类的解析类,所有的解析逻 辑在parser.parse(candidates)中

public void parse(Set<BeanDefinitionHolder> 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));
    }
-------------------
    protected void processConfigurationClass(ConfigurationClass configClass)
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);
}
// Otherwise ignore new imported config class; existing non- imported class overrides it.
return; }
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one. this.configurationClasses.remove(configClass); this.knownSuperclasses.values().removeIf(configClass::equals);
} }
// Recursively process the configuration class and its superclass hierarchy.
        SourceClass sourceClass = asSourceClass(configClass);
        do {
//循环处理bean,如果有父类,则处理父类,直至结束
 
10、继续跟进doProcessConfigurationClass方法,此方式是支持注解配置的核心逻辑
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
while (sourceClass != null); this.configurationClasses.put(configClass, configClass);
}

10、继续跟进doProcessConfigurationClass方法,此方式是支持注解配置的核心逻辑

/**
     * Apply processing and build a complete {@link ConfigurationClass} by
reading the
* annotations, members and methods from the source class. This method can
be called
* multiple times as relevant sources are discovered.
* @param configClass the configuration class being build
* @param sourceClass a source class
* @return the superclass, or {@code null} if none found or previously
processed */
@Nullable
    protected final SourceClass doProcessConfigurationClass(ConfigurationClass
configClass, SourceClass sourceClass)
            throws IOException {
//处理内部类逻辑,由于传来的参数是启动类,并不包含内部类,所以跳过
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // Recursively process any member (nested) classes first
            processMemberClasses(configClass, sourceClass);
        }
// 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注解来扫描项目中的bean 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 //遍历项目中的bean,如果是注解定义的bean,则进一步解析
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)) {
} }
}
//递归解析,所有的bean,如果有注解,会进一步解析注解中包含的bean
parse(bdCand.getBeanClassName(), holder.getBeanName()); }
// Process any @Import annotations //递归解析,获取导入的配置类,很多情况下,导入的配置类中会同样包含导入类注解 processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations //解析@ImportResource配置类 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 //处理@Bean注解修饰的类 Set<MethodMetadata> beanMethods =
retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 处理接口中的默认方法 processInterfaces(configClass, sourceClass);
 
11、查看获取配置类的逻辑
processImports(configClass, sourceClass, getImports(sourceClass), true);
/**
* Returns {@code @Import} class, considering all meta-annotations. */
    private Set<SourceClass> getImports(SourceClass sourceClass) throws
IOException {
        Set<SourceClass> imports = new LinkedHashSet<>();
        Set<SourceClass> visited = new LinkedHashSet<>();
        collectImports(sourceClass, imports, visited);
        return imports;
}
------------------
/**
* Recursively collect all declared {@code @Import} values. Unlike most * meta-annotations it is valid to have several {@code @Import}s declared
with
* different values; the usual process of returning values from the first * meta-annotation on a class is not sufficient.
* <p>For example, it is common for a {@code @Configuration} class to
declare direct
* {@code @Import}s in addition to meta-imports originating from an {@code
@Enable}
* annotation.
* 看到所有的bean都以导入的方式被加载进去
*/
    private void collectImports(SourceClass sourceClass, Set<SourceClass>
imports, Set<SourceClass> 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);
                }
}
12、继续回到ConfigurationClassParser中的parse方法中的最后一行,继续跟进该方法:
 imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
} }
 this.deferredImportSelectorHandler.process() -------------
public void process() {
List<DeferredImportSelectorHolder> 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<>(); }
}
---------------
  public void processGroupImports() {
            for (DeferredImportSelectorGrouping grouping :
this.groupings.values()) { grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(
entry.getMetadata());
                    try {
                        processImports(configurationClass,
asSourceClass(configurationClass), asSourceClasses(entry.getImportClassName()),
false);
configuration class [" +
}
catch (BeanDefinitionStoreException ex) {
throw ex; }
catch (Throwable ex) {
    throw new BeanDefinitionStoreException(
            "Failed to process import candidates for
configurationClass.getMetadata().getClassName() + "]", ex); }
}); }
}
------------
/**
* Return the imports defined by the group.
   
* @return each import with its associated configuration class
*/
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport :
this.deferredImports) { this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector()); return this.group.selectImports();
      } 
}
------------
}
public DeferredImportSelector getImportSelector() { return this.importSelector;
}
------------
@Override
        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 =
((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(),
annotationMetadata); this.autoConfigurationEntries.add(autoConfigurationEntry); for (String importClassName :
autoConfigurationEntry.getConfigurations()) { this.entries.putIfAbsent(importClassName, annotationMetadata);
      } 
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot自动装配原理是基于 Spring 框架的核心特性之一,即依赖注入(Dependency Injection)和控制反转(Inversion of Control)。通过自动装配SpringBoot 可以根据一定的规则,自动将需要的依赖对象注入到相应的组件中,简化了开发者的配置工作。 在 SpringBoot 中,自动装配主要通过以下几个步骤实现: 1. ComponentScan:SpringBoot 会根据指定的包路径进行组件扫描,找到所有被注解标记的组件,如 @Component、@Service、@Repository 等。 2. ConditionalOnClass/ConditionalOnMissingClass:SpringBoot 会根据类路径中是否存在指定的类来判断是否需要装配某个组件。当类存在时,装配该组件;当类不存在时,跳过该组件。 3. ConditionalOnBean/ConditionalOnMissingBean:SpringBoot 会根据容器中是否存在指定的 Bean 来判断是否需要装配某个组件。当 Bean 存在时,跳过该组件;当 Bean 不存在时,装配该组件。 4. EnableAutoConfiguration:SpringBoot 提供了一系列以 Enable 开头的注解,用于开启特定功能的自动配置。这些注解会在特定条件下加载一些默认的配置类,将默认的配置注入到容器中。 5. 自定义配置:除了 SpringBoot 提供的默认自动配置之外,开发者还可以通过自定义配置文件(application.properties 或 application.yml)来覆盖默认配置,实现个性化的自动装配。 总的来说,SpringBoot自动装配原理就是根据一系列的条件和规则,将需要的依赖对象自动注入到相应的组件中,简化了开发者的配置工作,提高了开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值