------本文只作为跟代码的一个参考,建议可以根据思路在指定类中断点调试学习----

1、运行被@SpringBootApplication修饰的程序入口,执行main方法,调用SpringApplication的静态run方法,返回ConfigurableApplicationContext。

2、在SpringApplication的静态run方法中创建了以启动类为参数的SpringApplication对象并调用了非静态run方法,构造方法和run方法内容如下

  1)首先解析SpringApplication构造方法的操作:

public SpringApplication(Class<?>... primarySources) {
        this((ResourceLoader)null, primarySources);
    }
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        // 用来在容器初始化之后,用来优雅停止的
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.resourceLoader = resourceLoader;
        // PrimarySources   启动类class对象
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        // 判断是否使用servlet容器启动,是否选择内置的servlet容器。SERVLET使用内嵌容器启动
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        // 通过读取META-INF/spring.factories配置创建springboot启动的初试化对象
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
     // 初始化监听类
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = this.deduceMainApplicationClass(); } private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) { return this.getSpringFactoriesInstances(type, new Class[0]); } private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = this.getClassLoader(); //使用工厂加载类读取spring.factories文件中配置的接口实现类的全限定名list Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); //使用反射根据全限定名执行构造方法生成对象 List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); // 根据实现的Ordered接口,实现getOrder返回的int值排序。没有实现这个接口的类不参与排序,原位置不变 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()); Iterator var7 = names.iterator(); while(var7.hasNext()) { String name = (String)var7.next(); try { Class<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass); //使用反射调用无参构造方法生成对象 Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); T instance = BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable var12) { throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12); } } return instances; }
SpringFactoriesLoader.loadFactoryNames(type, classLoader)源码如下:
 public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            try {
                Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                //底层封装的是LinkedHashMap,并对add方法进行了重写,保证从不同路径下的spring.factories读取到的同一个key都会在不同循环中都放在同一个key的value中,不会发生覆盖
                LinkedMultiValueMap result = new LinkedMultiValueMap();

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    // PropertiesLoaderUtils,spring的工具类,将配置文件流写入hashTable子类properties实例中--操作过程中只区分了是不是xml文件
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        int var10 = var9.length;

                        for(int var11 = 0; var11 < var10; ++var11) {
                            String factoryImplementationName = var9[var11];
                            result.add(factoryTypeName, factoryImplementationName.trim());
                        }
                    }
                }

                cache.put(classLoader, result);
                return result;
            } catch (IOException var13) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
            }
        }
    }
    
public void add(K key, @Nullable V value) {
        List<V> values = (List)this.targetMap.computeIfAbsent(key, (k) -> {
            return new LinkedList();
        });
        values.add(value);
    }
重写的add方法

相关文章:

  • 2021-04-13
  • 2021-12-10
  • 2021-12-05
  • 2021-11-23
猜你喜欢
  • 2021-06-08
  • 2022-12-23
  • 2021-10-05
  • 2022-01-29
  • 2021-09-07
  • 2022-01-15
  • 2021-08-16
相关资源
相似解决方案