一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - springboot 加載 META-INF/spring.factories方式

springboot 加載 META-INF/spring.factories方式

2022-02-10 15:04kong-kong Java教程

這篇文章主要介紹了springboot 加載 META-INF/spring.factories方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

springboot 加載 META-INF/spring.factories

用戶應用程序Application

?
1
ConfigurableApplicationContext context = SpringApplication.run(NacosSpringBootYamlApplication.class, args);

SpringApplication類

?
1
2
3
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
  return run(new Class<?>[] { primarySource }, args);
 }
?
1
2
3
4
// 這里Class是數組
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
  return new SpringApplication(primarySources).run(args);
 }
?
1
2
3
public SpringApplication(Class<?>... primarySources) {
  this(null, primarySources);
 }
?
1
2
3
4
5
6
7
8
9
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  this.resourceLoader = resourceLoader;
  Assert.notNull(primarySources, "PrimarySources must not be null");
  this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 這里就是SpringMvcApplication的實例
  this.webApplicationType = WebApplicationType.deduceFromClasspath();// deduce(推斷)web類型(servlet、reactive、NoWeb)
  setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 這里會處理加載所有的spring.factories文件的內容到緩存 找到*META-INF/spring.factories*中聲明的所有ApplicationContextInitializer的實現類并將其實例化
  setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //找到*META-INF/spring.factories*中聲明的所有ApplicationListener的實現類并將其實例化
  this.mainApplicationClass = deduceMainApplicationClass(); //獲得當前執行main方法的類對象,這里就是SpringMvcApplication的實例
 }

具體加載該classLoader下的所有spring.factories到緩存

如果緩存已經存在,則直接根據key,返回數據

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** key:是spring.factories的key    value:是根據key分組,把同個key的不同value放到list里面 */
 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
  MultiValueMap<String, String> result = cache.get(classLoader);
  if (result != null) { //已經處理過了  直接返回
   return result;
  }
//url: // file:/C:/Users/kongqi/.m2/repository/org/springframework/spring-beans/5.1.9.RELEASE/spring-beans-5.1.9.RELEASE.jar!/META-INF/spring.factories
  try { //得到classloader下的所有jar包中的spring.factories的文件
   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); // 得到spring.factories的內容
    for (Map.Entry<?, ?> entry : properties.entrySet()) { // key: spring.factories的key  value: spring.factories的value
     String factoryClassName = ((String) entry.getKey()).trim(); // spring.factories的key
     for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {//value根據逗號,分隔
      result.add(factoryClassName, factoryName.trim()); //factoryClassName其實就是spring.factories的key   由于value是List類型 MultiValueMap value有多個
     }
    }
   }
   cache.put(classLoader, result);
   return result;
  }
  catch (IOException ex) {
   throw new IllegalArgumentException("Unable to load factories from location [" +
     FACTORIES_RESOURCE_LOCATION + "]", ex);
  }
 }

流程圖

springboot 加載 META-INF/spring.factories方式

建立META-INF/spring.factories文件的意義何在

平常我們如何將Bean注入到容器當中

?
1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {
    @Autowired
    HelloProperties helloProperties;
    @Bean
    public HelloService helloService() {
        HelloService service = new HelloService();
        service.setHelloProperties( helloProperties  );
        return service;
    }
}

一般就建立配置文件使用@Configuration,里面通過@Bean進行加載bean

或者使用@Compont注解在類上進行類的注入

注意:

在我們主程序入口的時候:

@SpringBootApplication這個注解里面的東西

?
1
2
3
4
5
6
7
8
9
@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 {

里面注解@EnableAutoConfiguration

@ComponentScan注解指掃描@SpringBootApplication注解的入口程序類所在的basepackage下的

所有帶有@Component注解的bean,從而注入到容器當中。

但是

如果是加入maven坐標依賴的jar包,就是項目根目錄以外的Bean是怎么添加的??

這個時候注解@EnableAutoConfiguration的作用就來了

導入了AutoConfigurationImportSelector這個類:

這個類里面有一個方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * Return the auto-configuration class names that should be considered. By default
 * this method will load candidates using {@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 = 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;
}

@EnableAutoConfiguration注解來注冊項目包外的bean。而spring.factories文件,則是用來記錄項目包外需要注冊的bean類名

為什么需要spring.factories文件,

因為我們整個項目里面的入口文件只會掃描整個項目里面下的@Compont @Configuration等注解

但是如果我們是引用了其他jar包,而其他jar包只有@Bean或者@Compont等注解,是不會掃描到的。

除非你引入的jar包沒有Bean加載到容器當中

所以我們是通過寫/META-INF/spring.factories文件去進行加載的。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://kingkong.blog.csdn.net/article/details/104491907

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美四级无删版影片 | 亚洲高清国产拍精品动图 | 久久国产免费 | 成人国产在线播放 | 狠狠色婷婷日日综合五月 | 亚洲 欧美 中文 日韩 视频 | 91啦丨porny丨蝌蚪 | 羞羞视频麻豆 | 精品国产一区二区三区国产馆 | 欧亚精品一区二区三区 | 国产爱啪啪| 国产欧美va欧美va香蕉在线观看 | 免费观看成年肉动漫网站 | 日韩中文字幕网站 | 97色资源 | 免费毛片大全 | 日本在线观看www免费 | 五月天色网站 | 日韩版码免费福利视频 | 香蕉人人超人人超碰超国产 | 欧美一级一级做性视频 | 欧美兽皇video | 国产免费午夜高清 | 天天摸天天爽视频69视频 | 四虎永久网址影院 | 免费在线观看成年人视频 | m3u8久久国产精品影院 | 国产亚洲精品久久yy5099 | 天天草人人草 | 91se精品免费观看 | 99九九成人免费视频精品 | 女王调奴丨vk | 免费视频 久久久 | 欧美日韩亚洲国内综合网俺 | 羞羞答答影院在线 | 成人黄色免费网站 | 亚洲激情综合 | 国产在线播放一区 | 9自拍视频在线观看 | 久久九九久精品国产尤物 | 亚洲码和乱人伦中文一区 |