Spring Boot 之自动装配

痛定思痛。 2021-09-20 19:42 437阅读 0赞

前言

在最初接触spring 的时候,还是使用xml进行装配,我记得很清楚,当时分别配置了spring-dao.xml , spring-service.xml , spring-controller.xml。然后把所有需要用到的扫包,注入bean,以及配置,全都一股脑的塞进xml中,虽然出发点很好,不用在java代码中硬编码了,但是xml的可读性并不是很好,那阵子,真是痛苦的要命。

正文

后来逐渐的接触到了spring boot,发现这个东西开发起来简单的要命,几乎自己不需要过多的考虑spring 与别的框架整合的问题,所有的一切spring boot已经帮我们做好了,只需要在application.properties 配置一下就完事。
但是spring boot 因为大部分的东西,已经不需要我们在着手了,所以对我们而言,“易学难精”。所以我决定好好把spring boot的原理搞清楚,今天就来说一说自动装配。
这里提前说一下,Spring boot的注入一共有四种方式:

1.通过 spring 模式注解 装配
2.通过@Enable* 注解进行装配
3.通过条件注解装配
4.通过工厂类去加载

下面我会逐一说到以上这几点。

通过 spring 模式注解 装配

模式注解的方式,尽管我们刚开始接触spring,spring mvc 框架,我们也应该会知道他们到底是怎么使用的。
以@Component为首 派生的 @Controller,@Service, @Repository。分别对应了我们工程中的controller层,业务层,和数据持久层,这里我就不做过多结束了,只要把注解放在类上就可以被自动的注入到spring 的context中。

通过@Enable* 注解进行装配

很多人会问为什么有了模式注解的装备,还需要@Enable* 这个注解呢?
这个问题问的非常好,纵观整个Web的发展,我们可以看出来,是一个化繁为简的模块化趋势。
所以@Enable* 也是具有同样道理的,例如@EnableWebMvc就是一个web组件的集合。
@Enable注解有很多种:
例如说 @EnableAutoConfiguration,@EnableWebMvc,@EnableCaching,@EnableAsync等。
@Enable
的注入主要又可以分成两种:

1.使用注解的方式注入
2.使用接口编程的方式注入
Tips:但是不管是哪一种方式都是通过 @Enable* 注解定义上的@Import注解引入的。

使用注解的实现(是在Serlet3.0出现的)就是说在@Enable*的@Import注解中,加载的那个类是被@Configuration注入的,例如@EnableWebMvc。
代码如下:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package org.springframework.web.servlet.config.annotation;
  6. import java.lang.annotation.Documented;
  7. import java.lang.annotation.ElementType;
  8. import java.lang.annotation.Retention;
  9. import java.lang.annotation.RetentionPolicy;
  10. import java.lang.annotation.Target;
  11. import org.springframework.context.annotation.Import;
  12. @Retention(RetentionPolicy.RUNTIME)
  13. @Target({ElementType.TYPE})
  14. @Documented
  15. //这就是上面说的哪个@Import注解,我们继续查看下DelegatingWebMvcConfiguration 这个类
  16. @Import({DelegatingWebMvcConfiguration.class})
  17. public @interface EnableWebMvc {
  18. }

DelegatingWebMvcConfiguration 代码如下(只是摘取了部分,有所省略):

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package org.springframework.web.servlet.config.annotation;
  6. import java.util.List;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.format.FormatterRegistry;
  10. import org.springframework.http.converter.HttpMessageConverter;
  11. import org.springframework.lang.Nullable;
  12. import org.springframework.util.CollectionUtils;
  13. import org.springframework.validation.MessageCodesResolver;
  14. import org.springframework.validation.Validator;
  15. import org.springframework.web.method.support.HandlerMethodArgumentResolver;
  16. import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
  17. import org.springframework.web.servlet.HandlerExceptionResolver;
  18. @Configuration
  19. public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
  20. private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
  21. public DelegatingWebMvcConfiguration() {
  22. }
  23. @Autowired(
  24. required = false
  25. )
  26. public void setConfigurers(List<WebMvcConfigurer> configurers) {
  27. if (!CollectionUtils.isEmpty(configurers)) {
  28. this.configurers.addWebMvcConfigurers(configurers);
  29. }
  30. }
  31. protected void configurePathMatch(PathMatchConfigurer configurer) {
  32. this.configurers.configurePathMatch(configurer);
  33. }
  34. protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
  35. this.configurers.configureContentNegotiation(configurer);
  36. }
  37. //省略了之后的方法
  38. }

在这里可以很清楚的看到使用@Configuration(这个注解是替代原来在spring xml中注入而出现的注解)进行注入,虽然可以实现功能,但是每次只能注入指定的Bean。

使用编程的方式(是在Serlet3.1出现的)是在@Enable*的@Import注解中,加载的那个类,实现了ImportSelector接口,并且重写 selectImports(AnnotationMetadata importingClassMetadata)方法,可以将需要注入的class名称通过条件筛选后放在一个数组中通过返回值进行注入,这是一个我们一直在用的注解,但是为什么我们并不能在朝夕相处的spring boot 中找到相关的代码呢?因为Spring boot 对其进行了封装,下面我们慢慢顺藤摸瓜的去找一下。
新创建一个工程之后,映入眼帘的就是启动类 *Application.java:
代码如下:

  1. package com.harry.springtest;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class SpringtestApplication {
  6. public static void main(String[] args) {SpringApplication.run(SpringtestApplication.class, args);
  7. }
  8. }

在main方法中只有一个类的启动方法,那么我们就应该把关注点放在@SpringBootApplication上了
@SpringBootApplication 注解代码如下:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package org.springframework.boot.autoconfigure;
  6. import java.lang.annotation.Documented;
  7. import java.lang.annotation.ElementType;
  8. import java.lang.annotation.Inherited;
  9. import java.lang.annotation.Retention;
  10. import java.lang.annotation.RetentionPolicy;
  11. import java.lang.annotation.Target;
  12. import org.springframework.boot.SpringBootConfiguration;
  13. import org.springframework.boot.context.TypeExcludeFilter;
  14. import org.springframework.context.annotation.ComponentScan;
  15. import org.springframework.context.annotation.FilterType;
  16. import org.springframework.context.annotation.ComponentScan.Filter;
  17. import org.springframework.core.annotation.AliasFor;
  18. @Target({ElementType.TYPE})
  19. @Retention(RetentionPolicy.RUNTIME)
  20. @Documented
  21. @Inherited
  22. @SpringBootConfiguration
  23. @EnableAutoConfiguration
  24. @ComponentScan(
  25. excludeFilters = {@Filter(
  26. type = FilterType.CUSTOM,
  27. classes = {TypeExcludeFilter.class}
  28. ), @Filter(
  29. type = FilterType.CUSTOM,
  30. classes = {AutoConfigurationExcludeFilter.class}
  31. )}
  32. )
  33. public @interface SpringBootApplication {
  34. @AliasFor(
  35. annotation = EnableAutoConfiguration.class
  36. )
  37. Class<?>[] exclude() default {};
  38. @AliasFor(
  39. annotation = EnableAutoConfiguration.class
  40. )
  41. String[] excludeName() default {};
  42. @AliasFor(
  43. annotation = ComponentScan.class,
  44. attribute = "basePackages"
  45. )
  46. String[] scanBasePackages() default {};
  47. @AliasFor(
  48. annotation = ComponentScan.class,
  49. attribute = "basePackageClasses"
  50. )
  51. Class<?>[] scanBasePackageClasses() default {};
  52. }

在这里我们可以看出来@SpringBootApplication是一个组合注解里面运用到了@EnableAutoConfiguration,我们在继续看一下@EnableAutoConfiguration:

  1. package org.springframework.boot.autoconfigure;
  2. //省略应该引入的包
  3. public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
  4. private static final AutoConfigurationImportSelector.AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationImportSelector.AutoConfigurationEntry();
  5. private static final String[] NO_IMPORTS = new String[0];
  6. private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);
  7. private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
  8. private ConfigurableListableBeanFactory beanFactory;
  9. private Environment environment;
  10. private ClassLoader beanClassLoader;
  11. private ResourceLoader resourceLoader;
  12. public AutoConfigurationImportSelector() {
  13. }
  14. }
  15. //省略以下的所有方法。

DeferredImportSelector继承了ImportSelector

spring 条件装配

条件装配一共有两种方法,可以供我们使用:

1.使用@Profile注解
2.使用@Conditional注解

@Profile只是一个站在大局上的条件装配,通过环境变量的某些值,或者是系统变量某些定值,我们可以使用不同的实现方法。这就类似于我们定义了一个接口,通过多态,定义了两个实现类实现了相同的这个接口,但是我们可以通过环境变量去决定,到底是使用哪一个实现类去实现这个方法。
@Conditional注解,就更佳的灵活一些,类似于我们平常代码中的if else 通过判断出来的boolean值,决定到底是不是应该注入这个bean。
@Conditional代码如下:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package org.springframework.context.annotation;
  6. import java.lang.annotation.Documented;
  7. import java.lang.annotation.ElementType;
  8. import java.lang.annotation.Retention;
  9. import java.lang.annotation.RetentionPolicy;
  10. import java.lang.annotation.Target;
  11. @Target({ElementType.TYPE, ElementType.METHOD})
  12. @Retention(RetentionPolicy.RUNTIME)
  13. @Documented
  14. public @interface Conditional {
  15. Class<? extends Condition>[] value();
  16. }

我们可以看出来,需要往这个注解中加入一个值,这个值要实现Condition接口。
Condition接口的代码如下:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package org.springframework.context.annotation;
  6. import org.springframework.core.type.AnnotatedTypeMetadata;
  7. @FunctionalInterface
  8. public interface Condition {
  9. //关键之处
  10. boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
  11. }

关键的地方,就在这里了,我们在实现了这个接口的时候,得去重写这个match方法,如果需要注入的地方,就应该返回true,如果是觉得不符合条件,不应该注入的就返回false。
spring boot 通过封装 @Conditional 还有一些派生注解,如下:

@ConditionalOnBean(如果在当前context中存在这个bean,实例化bean)
@ConditionalOnClass(如果在classpath中有这个class,实例化 bean)
@ConditionalOnExpression(当表达式为true的时候,实例化一个bean)
@ConditionalOnMissingBean(如果在当前context中不存在这个bean,实例化一个bean)
@ConditionalOnMissingClass(如果在classpath中没有这个class,实例化一个bean)
@ConditionalOnNotWebApplication(不是web应用,实例化bean)

spring 工厂加载机制

在auto-configuration这个jar包下,或者其他自动注入的jar下,我们都可以看到spring.factories这个文件

  1. # Initializers
  2. org.springframework.context.ApplicationContextInitializer=\
  3. org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
  4. org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
  5. # Application Listeners
  6. org.springframework.context.ApplicationListener=\
  7. org.springframework.boot.autoconfigure.BackgroundPreinitializer
  8. # Auto Configuration Import Listeners
  9. org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
  10. org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
  11. # Auto Configuration Import Filters
  12. org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
  13. org.springframework.boot.autoconfigure.condition.OnClassCondition
  14. # Auto Configure
  15. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  16. org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
  17. org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
  18. org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
  19. org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
  20. org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
  21. org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
  22. org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
  23. org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
  24. org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
  25. org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
  26. org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
  27. org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
  28. org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
  29. org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
  30. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
  31. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
  32. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
  33. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
  34. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
  35. org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
  36. org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
  37. org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
  38. org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
  39. org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
  40. org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
  41. org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
  42. org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
  43. org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
  44. org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
  45. org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
  46. org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
  47. org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
  48. org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
  49. org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
  50. org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
  51. org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
  52. org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
  53. org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
  54. org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
  55. org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
  56. org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
  57. org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
  58. org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
  59. org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
  60. org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
  61. org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
  62. org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
  63. org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
  64. org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
  65. org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
  66. org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
  67. org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
  68. org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
  69. org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
  70. org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
  71. org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
  72. org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
  73. org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
  74. org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
  75. org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
  76. org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
  77. org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
  78. org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
  79. org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
  80. org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
  81. org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
  82. org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
  83. org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
  84. org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
  85. org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
  86. org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
  87. org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
  88. org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
  89. org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
  90. org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
  91. org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
  92. org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
  93. org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
  94. org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
  95. org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
  96. org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
  97. org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
  98. org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
  99. org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
  100. org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
  101. org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
  102. org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
  103. org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
  104. org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
  105. org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
  106. org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
  107. org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
  108. org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
  109. org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
  110. org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
  111. org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
  112. # Failure analyzers
  113. org.springframework.boot.diagnostics.FailureAnalyzer=\
  114. org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
  115. org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
  116. org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer
  117. # Template availability providers
  118. org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
  119. org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
  120. org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
  121. org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
  122. org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
  123. org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider

正是通过这个文件,我们把需要注入的类的全路径配在这里,但是问题来了,谁去读这个文件的呢?
在AutoConfigurationImportSelector.class中,我们可以看到以下方法:

  1. protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
  2. List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
  3. 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.");
  4. return configurations;
  5. }

我们继续刨根问底的看看SpringFactoriesLoader.loadFactoryNames 这个方法:

  1. public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
  2. String factoryClassName = factoryClass.getName();
  3. return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
  4. }

继续看loadSpringFactories 这个方法:

  1. private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
  2. MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
  3. if (result != null) {
  4. return result;
  5. } else {
  6. try {
  7. //就在这个地方将META-INF/spring.factories读入进来的。
  8. Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
  9. LinkedMultiValueMap result = new LinkedMultiValueMap();
  10. while(urls.hasMoreElements()) {
  11. URL url = (URL)urls.nextElement();
  12. UrlResource resource = new UrlResource(url);
  13. Properties properties = PropertiesLoaderUtils.loadProperties(resource);
  14. Iterator var6 = properties.entrySet().iterator();
  15. while(var6.hasNext()) {
  16. Entry<?, ?> entry = (Entry)var6.next();
  17. String factoryClassName = ((String)entry.getKey()).trim();
  18. String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
  19. int var10 = var9.length;
  20. for(int var11 = 0; var11 < var10; ++var11) {
  21. String factoryName = var9[var11];
  22. result.add(factoryClassName, factoryName.trim());
  23. }
  24. }
  25. }
  26. cache.put(classLoader, result);
  27. return result;
  28. } catch (IOException var13) {
  29. throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
  30. }
  31. }
  32. }

发表评论

表情:
评论列表 (有 0 条评论,437人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring Boot 自动装配原理

    > 本文已经收录到Github仓库,该仓库包含计算机基础、Java核心知识点、多线程、JVM、常见框架、分布式、微服务、设计模式、架构等核心知识点,欢迎star~ > > G