Spring boot 第六章 SpringApplication源码分析

1、概述

Spring boot 在进行SpringApplication对象实例化会加载 META/spring.factories文件,将该配置文件中的配置载入到Spring容器。

META/spring.factories 文件位置

输入图片说明

2、SpringApplication 源码分析

输入图片说明

输入图片说明

/**
	 * The location to look for factories.
	 * <p>Can be present in multiple JAR files.
	 */
	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";


/**
	 * Load the fully qualified class names of factory implementations of the
	 * given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given
	 * class loader.
	 * @param factoryClass the interface or abstract class representing the factory
	 * @param classLoader the ClassLoader to use for loading resources; can be
	 * {@code null} to use the default
	 * @see #loadFactories
	 * @throws IllegalArgumentException if an error occurs while loading factory names
	 */
	public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
		String factoryClassName = factoryClass.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
	}

	private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null)
			return result;
		try {
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					List<String> factoryClassNames = Arrays.asList(
							StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
					result.addAll((String) entry.getKey(), factoryClassNames);
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}

3、条件注解

@ConditionalOnBean : 当容器里有指定的bean的条件下

@ConditionalOnClass :当类路径下有指定的类的条件下

@ConditionalOnExpression : 基于SpEL表达式作为判断条件

@ConditionalOnJava : 基于jvm版本作为判断条件

@ConditionalOnJndi : 在 JNDI存在的条件下查找指定的位置

@ConditionalOnMissingBean : 当容器里没有指定的bean的情况下

@ConditionalOnMissingClass : 当类路径下没有指定的类的条件下

@ConditionalOnNotWebApplication : 当前项目不是web项目的条件下

@ConditionalOnProperty : 指定的属性是否有指定的值

@ConditionalOnResource : 类路径是否有指定的值

@ConditionalOnSingleCandidate : 当指定bean 在容器中只有一个,或者虽然有多个但是指定首选的bean

@ConditionalOnWebApplication : 当前项目时web项目的条件下

猜你喜欢

转载自my.oschina.net/u/3136594/blog/1790656