spring boot SpringApplication构造函数分析

来看下SpringApplication.java的构造函数大体流程图
在这里插入图片描述
来看下具体的函数截图在这里插入图片描述
1.resourceLoader成员变量的赋值,由于我们通过通过run(xx.class)方式来运行的.所以这种方式resourceLoader=null,
2.primarySources这个成员变量就是我们传来的class了.
3.webApplicationType这个按照我的理解,应该是WebApplicationType.SERVLET.
4.setInitializers.这个是获取需要初始化的对象,这个具体实现有点复杂,先来看截图在这里插入图片描述
这里是通过SpringFactoriesLoader类的loadFactoryNames函数来得到所有的需要初始化的类名.其实现方式在这里大体说一下.
1).通过传进来的classloader对象的getResources接口,获取URL
2).通过URL获取inputstream
3).Properties.load(inputstream)的方式读取文件中所有数据.其文件名为
public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;
4).对每一个property的value值,进行解析.因为其中可能包括多个类名.
5).通过反射的方式,获取传递进来Class的类名.然后将这个类名与所有的属性key进行比对,通过就返回value的list列表.大体是这样
这里传进来的是ApplicationContextInitializer.class.那么看我运行的程序打印在这里插入图片描述
看到没,第一行是key . factoryName.从第二行开始就是其需要获取的东西了.这里有四个需要初始化的类名.
获取了所有需要的类名后,还剩最后一步.就是实例化.看其实现在这里插入图片描述
这里首先是通过类名获取Class.
其实通过传递进来的paramerType参数,来得到其Constructor
再次就是使用反射的方式得到具体的实例了,这里需要注意的是args其实是个{},里面没数据.所以生成的对象构造函数里面应该都是赋的null值.
setInitializers最后一步是将所有的对象添加到list中去.

5.setListeners
这个具体实现与上面一模一样,只不过传的参数不一样,它传递的是ApplicationListener.class这个.来看下具体的获取的是什么,程序打印如下:在这里插入图片描述
6.构造函数最后一步mainApplicationClass成员变量的赋值.根据其执行的函数分析,其就是获取我们当前程序最初运行的类名.就是那个有main开始执行的类
最后贴下测试代码吧,有兴趣的可以自己试.
spring.factories //这个数据来源于spring.boot包下来的那个WEB_INFO

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\r
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
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

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer

# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

TestFactXml.java读取测试这个配置文件

package com.bruk;

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

public class TestFactXml {

    final static String FACTORIES_RESOURCE_LOCATION="spring.factories";

    public static void main(String[] args){
        ClassLoader load = Thread.currentThread().getContextClassLoader();
        HashMap<String,List<String>> map = new LinkedHashMap<>();
        System.out.println("args="+args);
        try {
            Enumeration<URL> urls = load.getResources(FACTORIES_RESOURCE_LOCATION);
            //result = new LinkedMultiValueMap<>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                System.out.println(url.getFile());
                // UrlResource resource = new UrlResource(url);
                //  Properties properties = PropertiesLoaderUtils.loadProperties(resource);

                InputStream inputStream = getInputStream(url);
                Properties props = new Properties();
                props.load(inputStream);
                for (Map.Entry<?, ?> entry : props.entrySet()) {
                    String factoryClassName = ((String) entry.getKey()).trim();
                    System.out.println("factoryClassName  "+factoryClassName);
                    for (String factoryName : delimitedListToStringArray((String) entry.getValue() , "," , null)) {
                        //result.add(factoryClassName, factoryName.trim());
                        System.out.println(factoryName.trim());
                        List<String> values = map.computeIfAbsent(factoryClassName, k -> new LinkedList<>());
                        values.add( factoryName);
                    }


                        // Set<String> names = new LinkedHashSet<>(map);
                    System.out.println("===========================================================");
                }
            }
            List<String> list= map.getOrDefault("org.springframework.context.ApplicationContextInitializer",Collections.emptyList());
            for (String name : list) {
                System.out.println("find name is "+name.trim());
            }
            }catch(Exception E){
            System.out.println(E.getMessage());
        }
    }

    public static String[] delimitedListToStringArray(
             String str,  String delimiter,  String charsToDelete) {

        if (str == null) {
            return new String[0];
        }
        if (delimiter == null) {
            return new String[]{str};
        }

        List<String> result = new ArrayList<>();
        if (delimiter.isEmpty()) {
            for (int i = 0; i < str.length(); i++) {
                result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
            }
        } else {
            int pos = 0;
            int delPos;
            while ((delPos = str.indexOf(delimiter, pos)) != -1) {
                result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
                pos = delPos + delimiter.length();
            }
            if (str.length() > 0 && pos <= str.length()) {
                // Add rest of String, but not in case of empty input.
                result.add(deleteAny(str.substring(pos), ","));
            }
        }
        Collection<String> collection = result;
        return collection.toArray(new String[0]);
    }

    public static String deleteAny(String inString,  String charsToDelete) {
        if (!hasLength(inString) || !hasLength(charsToDelete)) {
            return inString;
        }

        StringBuilder sb = new StringBuilder(inString.length());
        for (int i = 0; i < inString.length(); i++) {
            char c = inString.charAt(i);
            if (charsToDelete.indexOf(c) == -1) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static boolean hasLength( CharSequence str) {
        return (str != null && str.length() > 0);
    }

   static public InputStream getInputStream(URL url)  {

        //ResourceUtils.useCachesIfNecessary(con);
        try {
            URLConnection con = url.openConnection();
            return con.getInputStream();
        }  catch (Exception ex) {
            // Close the HTTP connection (if applicable).

        }
        return null;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bruk_spp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值