程序入库
源码如下:
@SpringBootApplication
public class SparkApplication {
public static void main(String[] args){
SpringApplication.run(SparkApplication.class,args);
}
}
一、@SpringBootApplication
- 完成了SpringBootConfiguration
- 完成了EnableAutoConfiguration中的自动配置
- 通过ComponentScan完成扫描
源码如下:
@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 {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};
@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "nameGenerator"
)
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
1.1 @SpringBootConfiguration
代理Bean方法为true。其中我们知道代码分为JAVA动态代理和CGLB代码两种代理情况。
原代码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
/**
* 动态代理Bean方法为ture
*/
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
1.2 @EnableAutoConfiguration
- AutoConfigurationPackage完成当前包下的配置信息
- AutoConfigurationImportSelector完成自动配置导入选择器,完成需要导入的类选择。
启动Spring应用上下文自动配置,参数猜想去配置你可能需要的Beans。
自动配置类通常基于类路径和定义的Bean来应用。
当使用SpringBootApplication,自动启动自动配置上下文,因此添加此注解不会产生额外的效果。
自动配置尝试尽可能智能化,并在您定义了更多自己的配置时退出自动配置值。
你可以随时手动配置任何您不想要的配置通过excludeName(),如果没有访问此方法(excludeName())权限,您也可以通过spring.autoconfigure.exclude
属性。自动配置总是应用于用户定义beans注册之后。
在包下类使用注册EnableAutoConfiguration
,通常基于SpringBootApplication
。具有特定意义通常采用·default·。
@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.
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
*/
String[] excludeName() default {};
}
1.2.1 AutoConfigurationPackage
- 返回需要自动配置包的名称
- 通过AutoConfigurationPackages.Registrar这个方法返回需要注册的包
说明Import会自动将当前类添加到Bean中
源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
/**
* 基础名称数组
*/
String[] basePackages() default {};
/**
* 基础包类数组
*/
Class<?>[] basePackageClasses() default {};
}
1.1.1.1 AutoConfigurationPackages.Registrar
源码如下:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
1.1.1.2 PackageImports
- 包名导入,看是否配置了basePackage的包名、配置了basePackageClass的包下类名称。
代码如下:
PackageImports(AnnotationMetadata metadata) {
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false));
List<String> packageNames = new ArrayList<>();
for (String basePackage : attributes.getStringArray("basePackages")) {
packageNames.add(basePackage);
}
for (Class<?> basePackageClass : attributes.getClassArray("basePackageClasses")) {
packageNames.add(basePackageClass.getPackage().getName());
}
if (packageNames.isEmpty()) {
packageNames.add(ClassUtils.getPackageName(metadata.getClassName()));
}
this.packageNames = Collections.unmodifiableList(packageNames);
}
一般获得的自动导入包名称为当前启动类的包名称:
public static String getPackageName(String fqClassName) {
Assert.notNull(fqClassName, "Class name must not be null");
int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR);
return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : "");
}
1.2.2 AutoConfigurationImportSelector
1 通过selectImports来获得选择需要导入的自动配置类
2 通过getAutoConfigurationEntry来完成第一步中获取SpringBoot自动配置入库类。
3 通过getAttributes方法获取注解元数据的属性
4 通过getCandidateConfigurations来获取自动配置类读取的文件是当前应用所有依赖的第三方ja下META-INF/spring.factories这个文件内容。
5. 通过removeDuplicates移除重复的类名称。
6. 通过getExclusions来获得需要排除的类。
7. 通过checkExcludedClasses来检查需要排除的类是否正确。
8. 在自动配置类中去除掉需要排除类。
9. 通过getConfigurationClassFilter来获得(META-INF/spring-autoconfigure-metadata.properties)中的自动配置元数据,过滤器匹配自动配置元数据和自动配置类相关内容。
10. 通过fireAutoConfigurationImportEvents来消除自动配置导入事件。
重要代码
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
//获取自动配置类入口
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);
}
getCandidateConfigurations重要代码解读获取自动配置类名称
//获取候选配置类名称
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;
}
//通过加载工厂获取自动配置类名称
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
//加载"META-INF/spring.factories中的数据,根据classLoader当前对象所处程序所有依赖jar的资源。
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()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
getConfigurationClassFilter来获取自动配置需要满足的信息
META-INF/spring-autoconfigure-metadata.properties
//获取配置类过滤器
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;
}
ConfigurationClassFilter(ClassLoader classLoader, List<AutoConfigurationImportFilter> filters) {
//获得自动配置类元数据
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(classLoader);
//自动配置导入过滤器
this.filters = filters;
}
//过滤掉在自动配置类元数据中不存在的类名称
List<String> filter(List<String> configurations) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
boolean skipped = false;
for (AutoConfigurationImportFilter filter : this.filters) {
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
if (!match[i]) {
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
List<String> result = new ArrayList<>(candidates.length);
for (String candidate : candidates) {
if (candidate != null) {
result.add(candidate);
}
}
if (logger.isTraceEnabled()) {
int numberFiltered = configurations.size() - result.size();
logger.trace("Filtered " + numberFiltered + " auto configuration class in "
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
}
return result;
}
//根据路径获取自动配置元数据
//PATH = "META-INF/spring-autoconfigure-metadata.properties"
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return loadMetadata(classLoader, PATH);
}
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
try {
Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
: ClassLoader.getSystemResources(path);
Properties properties = new Properties();
while (urls.hasMoreElements()) {
properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
}
return loadMetadata(properties);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);
}
}
二、SpringApplication
- SpringApplication应用上下文配置
- run启动
*/
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
/**
* 配置应用上下文
*/
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
初始化SpringApplication
WebApplicationType
NONE:不是一个WEB应用
SERVLET:是以Servlet的WEB应用程序
REACTIVE:是以Reactive的WEB应用程序
setInitializers:会设置初始化类
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
org.springframework.boot.context.ContextIdApplicationContextInitializer,
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
setListeners 设置监听类
org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.context.config.ConfigFileApplicationListener,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,
org.springframework.boot.context.logging.LoggingApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
ConfigFileApplicationListener
会自动搜索classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/这些目录
详情参考spring-boot.jar目录下META-INF/spring.factories
/**
* 创建一个SpringApplication实例
*/
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
/**
* 创建一个SpringApplication实例
* 判断Web应用类型
*
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//获得WEB应用程序类型:一般为SERVERL
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//设置初始化实例对象来自于读取ApplicationContextInitializer类所在jar下META-INF/spring.factories文件
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置监听实例对象来自于读取ApplicationListener类所在jar下META-INF/spring.factories文件
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//
this.mainApplicationClass = deduceMainApplicationClass();
}
//推动Main方法应用程序类
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
getSpringFactoriesInstances获取Spring工厂实例
- 其中SpringFactoriesLoader.loadFactoryNames(type, classLoader)是读取classLoader类所在jar下的
META-INF/spring.factories
文件信息 - 其中createSpringFactoriesInstances创建获取到的类名称,进行初始化实例。
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
//获取当前类
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
//获取类的构造方法
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
//执行构造方法获得实例
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
run方法执行
public ConfigurableApplicationContext run(String... args) {
//记时间秒表
StopWatch stopWatch = new StopWatch();
//启动秒表
stopWatch.start();
//配置应用上下文
ConfigurableApplicationContext context = null;
//配置头属性是否缺失
configureHeadlessProperty();
//获取Spring应用运行监听类
SpringApplicationRunListeners listeners = getRunListeners(args);
//监听开始
listeners.starting();
try {
//应用参数,可以传入特殊字符串如:--参数1,或是--key1=value1,或是参数1
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备应用环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//配置忽略bean信息到环境中
configureIgnoreBeanInfo(environment);
//在启动台打印Banner
Banner printedBanner = printBanner(environment);
//创建应用上下文:根据WEB类型创建不同的应用上下文
context = createApplicationContext();
//准备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新上下文: 因为在准备上下文时候初始化了一些信息需要重新载入Context
refreshContext(context);
//刷新上下文件之后:该方法未实现
afterRefresh(context, applicationArguments);
//计时秒表停止
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//监听器开始监听上下文
listeners.started(context);
//运行ApplicationRunner类和CommandLineRunner类。
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
getRunListeners(获得运行监听类)
读取SpringApplicationRunListener类jar下的META-INF/spring.factories
文件中类名称。
Spring应用上下文运行监听类
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
prepareEnvironment(准备环境)
- getOrCreateEnvironment中根据WEB应用类型创建或获取到对应类型的环境配置。
准备环境
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
//监听器环境准备
listeners.environmentPrepared(environment);
//将环境绑定到Spring应用
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
printBanner(打印横幅)
private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
//资源加载器
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(null);
//Spring应用横幅打印
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
if (this.bannerMode == Mode.LOG) {
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
//打印横幅
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
SpringApplicationBannerPrinter(ResourceLoader resourceLoader, Banner fallbackBanner) {
this.resourceLoader = resourceLoader;
this.fallbackBanner = fallbackBanner;
}
//打印横幅
Banner print(Environment environment, Class<?> sourceClass, Log logger) {
Banner banner = getBanner(environment);
try {
logger.info(createStringFromBanner(banner, environment, sourceClass));
}
catch (UnsupportedEncodingException ex) {
logger.warn("Failed to create String for banner", ex);
}
return new PrintedBanner(banner, sourceClass);
}
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
Banner banner = getBanner(environment);
banner.printBanner(environment, sourceClass, out);
return new PrintedBanner(banner, sourceClass);
}
//获取横幅,其中默认的SpringBoot,其他的自己配置
//图片横幅:在设置的时候key为spring.banner.image.location,支持类型"gif", "jpg", "png"
//字体横幅:在设置的时候key为spring.banner.location,支持类型txt文本。
private Banner getBanner(Environment environment) {
Banners banners = new Banners();
banners.addIfNotNull(getImageBanner(environment));
banners.addIfNotNull(getTextBanner(environment));
if (banners.hasAtLeastOneBanner()) {
return banners;
}
if (this.fallbackBanner != null) {
return this.fallbackBanner;
}
return DEFAULT_BANNER;
}
prepareContext(准备上下文)
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//将环境信息设置当上下文中
context.setEnvironment(environment);
//前置流程中会初始化默认:beanNameGenerator、resourceLoader、ConversionService实例
postProcessApplicationContext(context);
//应用初始设定
//在创建SpringApplication的时候,已经设置了需要初始化的类。将上下文件初始化到初始化类中。
applyInitializers(context);
//监听 准备上下文
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
//获取上下文中的Bean工厂
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//Bean工厂注册单例:应用参数注册为单例
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
//是否准备打印横幅
if (printedBanner != null) {
//注册打印横幅为单例
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
//如果Bean工厂,存在父类为DefaultListableBeanFactory
//设置允许Bean解析覆盖
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//懒加载初始化:上下文件添加Bean工厂后置处理器为LazyInitializationBeanFactoryPostProcessor
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
load(加载资源)
//在加载资源时会设置beanNameGenerator、resourceLoader、environment
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
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();
}
//其中loader.load()加载下面方法
int load() {
int count = 0;
for (Object source : this.sources) {
count += load(source);
}
return count;
}
//加载了对应的资源后,会返回当前加载资源数量
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class<?>) {
return load((Class<?>) source);
}
if (source instanceof Resource) {
return load((Resource) source);
}
if (source instanceof Package) {
return load((Package) source);
}
if (source instanceof CharSequence) {
return load((CharSequence) source);
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
总结
- ClassLoader:
- packages包含当前运行程序所有第三方依赖jar。
- path:包含当前应用的位置以及所有第三方jar的存储位置。
- 自动加载到所有第三方jar中的
"META-INF/spring.factories"
- 通过资源加载器,加载到文件中的信息。
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, 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()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}