当前位置: 首页 > news >正文

SpringBoot自动装配原理是什么?

1 创建上下文

public ConfigurableApplicationContext run(String... args) {//记录程序运行时间StopWatch stopWatch = new StopWatch();stopWatch.start();// ConfigurableApplicationContext Spring 的上下文ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();//从META-INF/spring.factories中获取监听器//1、获取并启动监听器SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//2、构造应用上下文环境ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);//处理需要忽略的BeanconfigureIgnoreBeanInfo(environment);//打印bannerBanner printedBanner = printBanner(environment);///3、初始化应用上下文context = createApplicationContext();//实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[]{ConfigurableApplicationContext.class}, context);//4、刷新应用上下文前的准备阶段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);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;}

2 刷新应用上下文前的准备阶段

private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {//设置容器环境context.setEnvironment(environment);//执行容器后置处理postProcessApplicationContext(context);//执行容器中的 ApplicationContextInitializer 包括spring.factories和通过三种方式自定义的applyInitializers(context);//向各个监听器发送容器已经准备好的事件listeners.contextPrepared(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beans//将main函数中的args参数封装成单例Bean,注册进容器context.getBeanFactory().registerSingleton("springApplicationArguments",applicationArguments);//将 printedBanner 也封装成单例,注册进容器if (printedBanner != null) {context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);}// Load the sourcesSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//加载我们的启动类,将启动类注入容器load(context, sources.toArray(new Object[0]));//发布容器已加载事件listeners.contextLoaded(context);}

3 实际执行的是BeanDefinitionLoader 的load方法

    protected void load(ApplicationContext context, Object[] sources) {if (logger.isDebugEnabled()) {logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));}//创建 BeanDefinitionLoaderBeanDefinitionLoader 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();}

4 判断是否资源类型,使用grovy加载还是注解加载方式

private int load(Object source) {Assert.notNull(source, "Source must not be null");// 从Class加载if (source instanceof Class<?>) {return load((Class<?>) source);}// 从Resource加载if (source instanceof Resource) {return load((Resource) source);}// 从Package加载if (source instanceof Package) {return load((Package) source);}// 从 CharSequence 加载 ???if (source instanceof CharSequence) {return load((CharSequence) source);}throw new IllegalArgumentException("Invalid source type " + source.getClass());}private int load(Class<?> source) {if (isGroovyPresent()&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {// Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,GroovyBeanDefinitionSource.class);load(loader);}if (isComponent(source)) {//将 启动类的 BeanDefinition注册进 beanDefinitionMapthis.annotatedReader.register(source);return 1;}return 0;}private void load(Resource source) {if (source.getFilename().endsWith(".groovy")) {if (this.groovyReader == null) {throw new BeanDefinitionStoreException("Cannot load Groovy beans without Groovy on classpath");}this.groovyReader.loadBeanDefinitions(source);}else {this.xmlReader.loadBeanDefinitions(source);}}

5 判断启动类中包含@Component注解

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

    private int load(Class<?> source) {if (isGroovyPresent()&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {// Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,GroovyBeanDefinitionSource.class);load(loader);}if (isComponent(source)) {//将 启动类的 BeanDefinition注册进 beanDefinitionMapthis.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 (MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY).isPresent(Component.class)) {return true;}// Nested anonymous classes are not eligible for registration, nor are groovy// closuresreturn !type.getName().matches(".*\\$_.*closure.*") && !type.isAnonymousClass()&& type.getConstructors() != null && type.getConstructors().length != 0;
}
​/*** 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 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));
​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);}}}

上面只是完成了启动对象的注入,自动装配还没有开始,下面开始进入到自动装配。

springboot3.0源码:没有了isComponent判断,可以直接注册组件

    private void load(Class<?> source) {if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {// Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());}if (isEligible(source)) {this.annotatedReader.register(source);}}private boolean isEligible(Class<?> type) {return !(type.isAnonymousClass() || isGroovyClosure(type) || hasNoConstructors(type));}

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

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// 自动装配入口invokeBeanFactoryPostProcessors(beanFactory);// 注册 bean后置处理器。registerBeanPostProcessors(beanFactory);beanPostProcess.end();// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.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();contextRefresh.end();}}}

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

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {//开始执行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注册的集合,否则加入到regularPostProcessorsfor (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {regularPostProcessors.add(postProcessor);}}
​// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// Separate between BeanDefinitionRegistryPostProcessors that implement// PriorityOrdered, Ordered, and the rest.List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
​// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.//通过BeanDefinitionRegistryPostProcessor获取到对应的处理类“org.springframework.context.annotation.internalConfigurationAnnotationProcessor”,但是需要注意的是这个类在springboot中搜索不到,这个类的完全限定名在AnnotationConfigEmbeddedWebApplicationContext中,在进行初始化的时候会装配几个类,在创建AnnotatedBeanDefinitionReader对象的时候会将该类注册到bean对象中,此处可以看到internalConfigurationAnnotationProcessor为bean名称,容器中真正的类是ConfigurationClassPostProcessorString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);//首先执行类型为PriorityOrdered的BeanDefinitionRegistryPostProcessor//PriorityOrdered类型表明为优先执行for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {//获取对应的beancurrentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//用来存储已经执行过的BeanDefinitionRegistryPostProcessorprocessedBeans.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类型的BeanDefinitionRegistryPostProcessorboolean 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);}
​// Do not initialize FactoryBeans here: We need to leave all regular beans// 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}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));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
​// Clear cached merged bean definitions since the post-processors might have// 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,如果有父类,则处理父类,直至结束sourceClass = doProcessConfigurationClass(configClass, sourceClass);}while (sourceClass != null);this.configurationClasses.put(configClass, configClass);}

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

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)throws IOException {//处理内部类逻辑,由于传来的参数是启动类,并不包含内部类,所以跳过if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes firstprocessMemberClasses(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注解来扫描项目中的beanSet<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 neededfor (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();if (bdCand == null) {bdCand = holder.getBeanDefinition();}if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {//递归解析,所有的bean,如果有注解,会进一步解析注解中包含的beanparse(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);// 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 recursereturn sourceClass.getSuperClass();}}// No superclass -> processing is completereturn null;}

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);}}imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));}}

12、继续回到ConfigurationClassParser中的parse方法中的最后一行,继续跟进该方法

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);}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +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;}
------------@Overridepublic 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);}}

相关文章:

  • 互联网医院开发:引领智慧医疗新时代
  • Mac安装配置maven
  • KDE-Ambari-Metrics-Collector问题排查解决手册
  • 企业防泄密软件有哪些,哪个排名最好
  • 指针数组与数组指针的理解
  • 前端基础:1-2 面向对象 + Promise
  • 4、设计模式之工厂模式
  • C语言常用的内存操作函数
  • 打豆豆game
  • 带你玩转OpenHarmony AI:打造智能语音子系统
  • SpringBoot基础详解
  • 指针变量加1为什么地址加了4?
  • Python01:初入Python(Mac)
  • 【计算机视觉(3)】
  • Docker 安装最新版MongoDB 限制内存 配置权限
  • $translatePartialLoader加载失败及解决方式
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Angular Elements 及其运作原理
  • Docker下部署自己的LNMP工作环境
  • ES10 特性的完整指南
  • Gradle 5.0 正式版发布
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • js面向对象
  • NSTimer学习笔记
  • SOFAMosn配置模型
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 番外篇1:在Windows环境下安装JDK
  • 机器学习中为什么要做归一化normalization
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 老板让我十分钟上手nx-admin
  • 如何选择开源的机器学习框架?
  • 时间复杂度与空间复杂度分析
  • 自动记录MySQL慢查询快照脚本
  • 《码出高效》学习笔记与书中错误记录
  • puppet连载22:define用法
  • ​2020 年大前端技术趋势解读
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #162 (Div. 2)
  • #面试系列-腾讯后端一面
  • (2)STM32单片机上位机
  • (floyd+补集) poj 3275
  • (ibm)Java 语言的 XPath API
  • (代码示例)使用setTimeout来延迟加载JS脚本文件
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (文章复现)基于主从博弈的售电商多元零售套餐设计与多级市场购电策略
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • ****三次握手和四次挥手