小记spring-boot自动加载

自动配置:

通过 @EnableAutoConfiguration 或者@SpringBootApplication注解 开启组件扫描和自动配置

通过@SpringBootApplication(exclude = XAutoConfiguration.class)关闭自动配置,自动配置位于

org.springframework.boot.autoconfigure包路径。

有一个名为getAutoConfigurationEntry的方法,这个方法发挥的作用是扫描ClassPath下的所有jar包的spring.factories文件,将spring.factories文件keyEnableAutoConfiguration的所有值取出,然后这些值其实是类的全限定名,也就是自动配置类的全限定名,然后 Spring Boot 通过这些全限定名进行类加载(反射),将这些自动配置类添加到 Spring 容器中

/**
 * 加载AutoConfigurationImportSelector
 */
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...    
/**
 *加载AutoConfigurationImportSelector
 *实现DeferredImportSelector,BeanClassLoaderAware,ResourceLoaderAware,BeanFactoryAware,Ordered
 */
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
            ...
                
     /**
      * 实现DeferredImportSelector的selectImports方法
      */
 	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
            
       /**
        *返回基于@Configuration的需要被自动加载的类
        *Return the AutoConfigurationImportSelector.AutoConfigurationEntry based on the    
        *AnnotationMetadata of the importing @Configuration class.
        *Params:
        *annotationMetadata – the annotation metadata of the configuration class
        *Returns:
        *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);
	}
      /**
       *返回META-INF/spring.factories里面配置的类
       *(org.springframework.boot.autoconfigure.EnableAutoConfiguration=后面的配置)
       *Return the auto-configuration class names that should be considered. By default this method          *will load candidates using SpringFactoriesLoader with getSpringFactoriesLoaderFactoryClass().
       *Params:
       *metadata – the source metadata
       *attributes – the annotation attributes
       *Returns:
       *a list of candidate configurations
       */
      protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}
       
     
  1. DeferredImportSelector 继承ImportSelector

    ImportSelector : ImportSelector implementations are usually processed in the same way as regular @Import annotations, however, it is also possible to defer(延迟) selection of imports until all @Configuration classes have been processed (see DeferredImportSelector for details).(所有的@Configuration已经被process)

    DeferredImportSelector :A variation of ImportSelector that runs after all @Configuration beans have been processed. This type of selector can be particularly useful when the selected imports are @Conditional.(配合@Conditional)

  2. BeanClassLoaderAware

  3. ResourceLoaderAware 可以被ResourceLoader通知,也可以通过实现ApplicationContextAware,获得ApplicationContext对象,ApplicationContext继承了ResourceLoader接口

    Interface to be implemented by any object that wishes to be notified of the ResourceLoader (typically the ApplicationContext) that it runs in. This is an alternative to a full ApplicationContext dependency via the ApplicationContextAware interface.
    
  4. BeanFactoryAware

  5. Ordered 指定顺序

    Ordered is an interface that can be implemented by objects that should be orderable, for example in a Collection.
    The actual order can be interpreted as prioritization, with the first object (with the lowest order value) having the highest priority.

	/**
	  * SpringFactoriesLoader.loadSpringFactories
	  * 该类位于spring-core包,加载FACTORIES_RESOURCE_LOCATION也就是META-INF/spring.factories文件的配置
	  */
     private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
		Map<String, List<String>> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		result = new HashMap<>();
		try {
			Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryTypeName = ((String) entry.getKey()).trim();
					String[] factoryImplementationNames =
							StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
					for (String factoryImplementationName : factoryImplementationNames) {
						result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
								.add(factoryImplementationName.trim());
					}
				}
			}

			// Replace all lists with unmodifiable lists containing unique elements
			result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
					.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
			cache.put(classLoader, result);
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
		return result;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值