zoukankan      html  css  js  c++  java
  • Spring Boot 工厂加载机制 SpringFactoriesLoader

    SpringFactoriesLoader 介绍

    框架内部使用的通用工厂加载机制

    从classpath下多个jar包特定的位置读取文件并初始化类

    文件内容必须是kv形式,即properties类型

    key是全限定名(抽象类|接口)、value是实现,多个用逗号分隔

    SpringFactoriesLoader作用

    SpringBoot框架中从类路径jar包中读取特定文件实现扩展类的载入

    将所有Jar中的spring.factories(A.jar(spring.factories),

       B.jar(spring.factories),

        C.jar(spring.factories)

       ......

    )载入 Spring Boot框架

    SpringFactoriesLoader在什么时候加载系统初始化器呢?

       

    查看源码

    从启动类开始

    SpringApplication.run(Sb2Application.class, args);
    

      

    1、进入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);
    }
    	
    public SpringApplication(Class<?>... primarySources) {
    	this(null, primarySources);
    }
    

      

    2、进入SpringApplication构造函数

    	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    		this.resourceLoader = resourceLoader;
    		Assert.notNull(primarySources, "PrimarySources must not be null");
    		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    		this.webApplicationType = WebApplicationType.deduceFromClasspath();
    		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    		this.mainApplicationClass = deduceMainApplicationClass();
    	}
    

      

    3、然后进入setInitializers方法

    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

    4、进入getSpringFactoriesInstances方法

    5、然后进入loadFactoryNames方法

    6、然后进入loadFactoryNames方法

     上面代码对应loadFactories的流程图

     

     可以发现FACTORIES_RESOURCE_LOCATION的值为"META-INF/spring.factories"。 这就是为什么我们前面要在META-INF文件夹下创建spring.factories 文件的原因。

    获得所有Jar包下的META-INF/spring.factories文件

    classLoader.getResources(FACTORIES_RESOURCE_LOCATION)

    通过以下过程,将初始化器注入到容器当中

    for (Map.Entry<?, ?> entry : properties.entrySet()) {
    String factoryClassName = ((String) entry.getKey()).trim();
    for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
    result.add(factoryClassName, factoryName.trim());
    }
    }
    如下图,Debug显示的所有系统初始化器

     names返回7个初始化器

     7、然后实例化这7个初始化器

     通过反射进行实例化

     8、通过setInitializers将初始化器实例注入到spring容器中

    	public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {
    		this.initializers = new ArrayList<>();
    		this.initializers.addAll(initializers);
    	}
    

      

    
    
  • 相关阅读:
    Android studio 中国的垃圾问题解决
    实现一个简单的boot
    代理下载android4.4源代码
    《程序员在第一季度追姐姐的书》——提升自己的形象气质
    第46周四
    Spring单例与线程安全小结
    2014第46周二
    第46周一
    第45周日
    第45周六
  • 原文地址:https://www.cnblogs.com/linlf03/p/12269834.html
Copyright © 2011-2022 走看看