SpringBoot-2.7.6自动装配过程

文章目录

  • 前言
  • 一、自动装配主要节点图
  • 二、自动装配主要组件
    • 1.注解
      • 1.1.应用入口注解-@SpringBootApplication
      • 1.2.启动自动配置-@EnableAutoConfiguration注解
      • 1.3.自动配置包-@AutoConfigurationPackage注解
    • 2.关键类
      • 2.1.自动配置选择器-AutoConfigurationImportSelector
      • 2.2.配置类处理器-ConfigurationClassPostProcessor
      • 2.3.配置类解析器-ConfigurationClassParser
        • 2.3.1.延迟导入选择器处理器-DeferredImportSelectorHandler
        • 2.3.2.分组延迟导入选择器处理器-DeferredImportSelectorGroupingHandler
        • 2.3.3.分组延迟导入选择器-DeferredImportSelectorGrouping
  • 三、自动装配完整流程
    • 1.自动装配流程图
    • 2.自动装配流程图各步骤说明
      • 2.1.应用启动-SpringApplication.run()
      • 2.2.应用容器刷新-AbstractApplicationContext.refresh()
      • 2.3.读取并设置Bean定义-PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
      • 2.4.读取并设置配置类Bean-ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()
      • 2.5.配置类元信息解析-ConfigurationClassParser.parser()
        • 2.5.1.选择器处理器处理配置类信息-DeferredImportSelectorHandler.process()
        • 2.5.2.分组选择器处理器注册分组选择器持有者-DeferredImportSelectorGroupingHandler.register()
          • 2.5.2.1.获取自动配置导入选择器的类型(默认为分组类型)-AutoConfigurationImportSelector.getImportGroup()
        • 2.5.3.分组选择器处理器导入组内配置-DeferredImportSelectorGroupingHandler.processGroupImports()
        • 2.5.4.选择器组执行批量导入配置-DeferredImportSelectorGrouping.getImports()
          • 2.5.4.1.分组选择器实现类加载配置-AutoConfigurationGroup.process()
          • 2.5.4.2.分组选择器实现类导入配置-AutoConfigurationGroup.selectImports()
  • 总结


前言

SpringBoot的自动装配是拆箱即用的基础,也是微服务化的前提。我们在熟练使用springboot的时候,能否也能熟悉它完整的自动装配的过程?接下来我们就透过源代码来把握自动装配的来龙去脉。以下所有内容都是基于SpringBoot-2.7.6版本来的,版本不同自动装配的流程或许会有差异,在参照本文调试源码时要注意本地的SpringBoot版本。


一、自动装配主要节点图

SpringBoot自动装配主要节点图,如下:
SpringBoot-2.7.6自动装配过程_第1张图片

二、自动装配主要组件

1.注解

1.1.应用入口注解-@SpringBootApplication

@SpringBootApplication是spring boot的主配置类,启动全部依赖这个配置类,里面包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan,此处@ComponentScan由于没有指定扫描包,因此它默认扫描的是与该类同级的类或者同级包下的所有类,另外@SpringBootConfiguration,通过源码得知它是一个@Configuration,因此@SpringBootApplication等同于@Configuration @ComponentScan @EnableAutoConfiguration。源码如下:

/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.repository.Repository;

/**
 * Indicates a {@link Configuration configuration} class that declares one or more
 * {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
 * auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
 * annotation that is equivalent to declaring {@code @Configuration},
 * {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @author Andy Wilkinson
 * @since 1.2.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
   

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {
   };

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {
   };

	/**
	 * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
	 * for a type-safe alternative to String-based package names.
	 * 

* Note: this setting is an alias for * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity} * scanning or Spring Data {@link Repository} scanning. For those you should add * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and * {@code @Enable...Repositories} annotations. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default { }; /** * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to * scan for annotated components. The package of each class specified will be scanned. *

* Consider creating a special no-op marker class or interface in each package that * serves no purpose other than being referenced by this attribute. *

* Note: this setting is an alias for * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity} * scanning or Spring Data {@link Repository} scanning. For those you should add * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and * {@code @Enable...Repositories} annotations. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default { }; /** * The {@link BeanNameGenerator} class to be used for naming detected components * within the Spring container. *

* The default value of the {@link BeanNameGenerator} interface itself indicates that * the scanner used to process this {@code @SpringBootApplication} annotation should * use its inherited bean name generator, e.g. the default * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the * application context at bootstrap time. * @return {@link BeanNameGenerator} to use * @see SpringApplication#setBeanNameGenerator(BeanNameGenerator) * @since 2.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator") Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; /** * Specify whether {@link Bean @Bean} methods should get proxied in order to enforce * bean lifecycle behavior, e.g. to return shared singleton bean instances even in * case of direct {@code @Bean} method calls in user code. This feature requires * method interception, implemented through a runtime-generated CGLIB subclass which * comes with limitations such as the configuration class and its methods not being * allowed to declare {@code final}. *

* The default is {@code true}, allowing for 'inter-bean references' within the * configuration class as well as for external calls to this configuration's * {@code @Bean} methods, e.g. from another configuration class. If this is not needed * since each of this particular configuration's {@code @Bean} methods is * self-contained and designed as a plain factory method for container use, switch * this flag to {@code false} in order to avoid CGLIB subclass processing. *

* Turning off bean method interception effectively processes {@code @Bean} methods * individually like when declared on non-{@code @Configuration} classes, a.k.a. * "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore behaviorally * equivalent to removing the {@code @Configuration} stereotype. * @since 2.2 * @return whether to proxy {@code @Bean} methods */ @AliasFor(annotation = Configuration.class) boolean proxyBeanMethods() default true; }

1.2.启动自动配置-@EnableAutoConfiguration注解

  • @AutoConfigurationPackage:自动获取主类的包名放入到扫描器
  • @Import(AutoConfigurationImportSelector.class):选择器,满足条件自动把所依赖的三方依赖包引入。源码如下:
/*
 * Copyright 2012-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.SpringFactoriesLoader;

/**
 * Enable auto-configuration of the Spring Application Context, attempting to guess and
 * configure beans that you are likely to need. Auto-configuration classes are usually
 * applied based on your classpath and what beans you have defined. For example, if you
 * have {@code tomcat-embedded.jar} on your classpath you are likely to want a
 * {@link TomcatServletWebServerFactory} (unless you have defined your own
 * {@link ServletWebServerFactory} bean).
 * 

* When using {@link SpringBootApplication @SpringBootApplication}, the auto-configuration * of the context is automatically enabled and adding this annotation has therefore no * additional effect. *

* Auto-configuration tries to be as intelligent as possible and will back-away as you * define more of your own configuration. You can always manually {@link #exclude()} any * configuration that you never want to apply (use {@link #excludeName()} if you don't * have access to them). You can also exclude them via the * {@code spring.autoconfigure.exclude} property. Auto-configuration is always applied * after user-defined beans have been registered. *

* The package of the class that is annotated with {@code @EnableAutoConfiguration}, * usually via {@code @SpringBootApplication}, has specific significance and is often used * as a 'default'. For example, it will be used when scanning for {@code @Entity} classes. * It is generally recommended that you place {@code @EnableAutoConfiguration} (if you're * not using {@code @SpringBootApplication}) in a root package so that all sub-packages * and classes can be searched. *

* Auto-configuration classes are regular Spring {@link Configuration @Configuration} * beans. They are located using {@link ImportCandidates} and the * {@link SpringFactoriesLoader} mechanism (keyed against this class). Generally * auto-configuration beans are {@link Conditional @Conditional} beans (most often using * {@link ConditionalOnClass @ConditionalOnClass} and * {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations). * * @author Phillip Webb * @author Stephane Nicoll * @since 1.0.0 * @see ConditionalOnBean * @see ConditionalOnMissingBean * @see ConditionalOnClass * @see AutoConfigureAfter * @see SpringBootApplication */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { /** * Environment property that can be used to override when auto-configuration is * enabled. */ String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class<?>[] exclude() default { }; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ String[] excludeName() default { }; }

1.3.自动配置包-@AutoConfigurationPackage注解

@AutoConfigurationPackage里面的Registrar.class类获取到项目的源数据,然后获取@SpringBootApplication注解(主入口)所在类的包名,获取到包名后自动把该包以及子包添加到注解扫描器里面。

2.关键类

2.1.自动配置选择器-AutoConfigurationImportSelector

AutoConfigurationImportSelector实现了DeferredImportSelector接口,这个接口继承了ImportSelector。ImportSelector接口主要是为了导入@Configuration的配置项,而DeferredImportSelector是延期导入,当所有的@Configuration都处理过后才会执行。继承关系和源码如下:

SpringBoot-2.7.6自动装配过程_第2张图片

/*
 * Copyright 2012-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

/**
 * {@link DeferredImportSelector} to handle {@link EnableAutoConfiguration
 * auto-configuration}. This class can also be subclassed if a custom variant of
 * {@link EnableAutoConfiguration @EnableAutoConfiguration} is needed.
 *
 * @author Phillip Webb
 * @author Andy Wilkinson
 * @author Stephane Nicoll
 * @author Madhura Bhave
 * @author Moritz Halbritter
 * @since 1.3.0
 * @see EnableAutoConfiguration
 */
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
   

	private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();

	private static final String[] NO_IMPORTS = {
   };

	private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);

	private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";

	private ConfigurableListableBeanFactory beanFactory;

	private Environment environment;

	private ClassLoader beanClassLoader;

	private ResourceLoader resourceLoader;

	private ConfigurationClassFilter configurationClassFilter;

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
   
		if (!isEnabled(annotationMetadata)) {
   
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

	@Override
	public Predicate<String> getExclusionFilter() {
   
		return this::shouldExclude;
	}

	private boolean shouldExclude(String configurationClassName) {
   
		return getConfigurationClassFilter().filter(Collections.singletonList(configurationClassName)).isEmpty();
	}

	/**
	 * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
	 * of the importing {@link Configuration @Configuration} class.
	 * @param annotationMetadata the annotation metadata of the configuration class
	 * @return the auto-configurations that should be imported
	 */
	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
   
		if (!isEnabled(annotationMetadata)) {
   
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

	@Override
	public Class<? extends Group> getImportGroup() {
   
		return AutoConfigurationGroup.class;
	}

	protected boolean isEnabled(AnnotationMetadata metadata) {
   
		if (getClass() == AutoConfigurationImportSelector.class) {
   
			return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
		}
		return true;
	}

	/**
	 * Return the appropriate {@link AnnotationAttributes} from the
	 * {@link AnnotationMetadata}. By default this method will return attributes for
	 * {@link #getAnnotationClass()}.
	 * @param metadata the annotation metadata
	 * @return annotation attributes
	 */
	protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
   
		String name = getAnnotationClass().getName();
		AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
		Assert.notNull(attributes, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
				+ " annotated with " + ClassUtils.getShortName(name) + "?");
		return attributes;
	}

	/**
	 * Return the source annotation class used by the selector.
	 * @return the annotation class
	 */
	protected Class<?> getAnnotationClass() {
   
		return EnableAutoConfiguration.class;
	}

	/**
	 * Return the auto-configuration class names that should be considered. By default
	 * this method will load candidates using {@link ImportCandidates} with
	 * {@link #getSpringFactoriesLoaderFactoryClass()}. For backward compatible reasons it
	 * will also consider {@link SpringFactoriesLoader} with
	 * {@link #getSpringFactoriesLoaderFactoryClass()}.
	 * @param metadata the source metadata
	 * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
	 * attributes}
	 * @return a list of candidate configurations
	 */
	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
   
		List<String> configurations = new ArrayList<>(
				SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
		ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

	/**
	 * Return the class used by {@link SpringFactoriesLoader} to load configuration
	 * candidates.
	 * @return the factory class
	 */
	protected Class<?> getSpringFactoriesLoaderFactoryClass() {
   
		return EnableAutoConfiguration.class;
	}

	private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
   
		List<String> invalidExcludes = new ArrayList<>(exclusions.size());
		for (String exclusion : exclusions) {
   
			if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
   
				invalidExcludes.add(exclusion);
			}
		}
		if (!invalidExcludes.isEmpty()) {
   
			handleInvalidExcludes(invalidExcludes);
		}
	}

	/**
	 * Handle any invalid excludes that have been specified.
	 * @param invalidExcludes the list of invalid excludes (will always have at least one
	 * element)
	 */
	protected void handleInvalidExcludes(List<String> invalidExcludes) {
   
		StringBuilder message = new StringBuilder();
		for (String exclude : invalidExcludes) {
   
			message.append("\t- ").append(exclude).append(String.format("%n"));
		}
		throw new IllegalStateException(String.format(
				"The following classes could not be excluded because they are not auto-configuration classes:%n%s",
				message));
	}

	/**
	 * Return any exclusions that limit the candidate configurations.
	 * @param metadata the source metadata
	 * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
	 * attributes}
	 * @return exclusions or an empty set
	 */
	protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
   
		Set<String> excluded = new LinkedHashSet<>();
		excluded.addAll(asList(attributes, "exclude"));
		excluded.addAll(asList(attributes, "excludeName"));
		excluded.addAll(getExcludeAutoConfigurationsProperty());
		return excluded;
	}

	/**
	 * Returns the auto-configurations excluded by the
	 * {@code spring.autoconfigure.exclude} property.
	 * @return excluded auto-configurations
	 * @since 2.3.2
	 */
	protected List<String> getExcludeAutoConfigurationsProperty() {
   
		Environment environment = getEnvironment();
		if (environment == null) {
   
			return Collections.emptyList();
		}
		if (environment instanceof ConfigurableEnvironment) {
   
			Binder binder = Binder.get(environment);
			return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList)
					.orElse(Collections.emptyList());
		}
		String[] excludes = environment.getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
		return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
	}

	protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
   
		return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
	}

	private ConfigurationClassFilter getConfigurationClassFilter() {
   
		if (this.configurationClassFilter == null) {
   
			List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters();
			for (AutoConfigurationImportFilter filter : filters) {
   
				invokeAwareMethods(filter);
			}
			this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
		}
		return this.configurationClassFilter;
	}

	protected final <T> List<T> removeDuplicates(List<T> list) {
   
		return new ArrayList<>(new LinkedHashSet<>(list));
	}

	protected final List<String> asList(AnnotationAttributes attributes, String name) {
   
		String[] value = attributes.getStringArray(name);
		return Arrays.asList(value);
	}

	private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
   
		List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
		if (!listeners.isEmpty()) {
   
			AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
			for (AutoConfigurationImportListener listener : listeners) {
   
				invokeAwareMethods(listener);
				listener.onAutoConfigurationImportEvent(event);
			}
		}
	}

	protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
   
		return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
	}

	private void invokeAwareMethods(Object instance) {
   
		if (instance instanceof Aware) {
   
			if (instance instanceof BeanClassLoaderAware) {
   
				((BeanClassLoaderAware) instance).setBeanClassLoader(this.beanClassLoader);
			}
			if (instance instanceof BeanFactoryAware) {
   
				((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);
			}
			if (instance instanceof EnvironmentAware) {
   
				((EnvironmentAware) instance).setEnvironment(this.environment);
			}
			if (instance instanceof ResourceLoaderAware) {
   
				((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);
			}
		}
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
   
		Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
		this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
	}

	protected final ConfigurableListableBeanFactory getBeanFactory() {
   
		return this.beanFactory;
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
   
		this.beanClassLoader = classLoader;
	}

	protected ClassLoader getBeanClassLoader() {
   
		return this.beanClassLoader;
	}

	@Override
	public void setEnvironment(Environment environment) {
   
		this.environment = environment;
	}

	protected final Environment getEnvironment() {
   
		return this.environment;
	}

	@Override
	public void setResourceLoader(ResourceLoader resourceLoader) {
   
		this.resourceLoader = resourceLoader;
	}

	protected final ResourceLoader getResourceLoader() {
   
		return this.resourceLoader;
	}

	@Override
	public int getOrder() {
   
		return Ordered.LOWEST_PRECEDENCE - 1;
	}

	private static class ConfigurationClassFilter {
   

		private final AutoConfigurationMetadata autoConfigurationMetadata;

		private final List<AutoConfigurationImportFilter> filters;

		ConfigurationClassFilter(ClassLoader classLoader, List<AutoConfigurationImportFilter> filters) {
   
			this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(classLoader);
			this.filters = filters;
		}

		List<String> filter(List<String> configurations

你可能感兴趣的:(spring,spring,boot,java,后端)