Spring Boot-源码阅读-启动主流程(一)

说明

待定

 

main方法

通过以下方法就完成了自定义启动和容器初始化是怎么完成的呢

@SpringBootApplication
public class FinancialAnalysisApplication {

    public static void main(String[] args) {
//<1>run启动 SpringApplication.run(FinancialAnalysisApplication.
class, args); } }

<1>

org.springframework.boot.SpringApplication#run

 public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        //包装成数组类型 我们表示我们可以配置多个
        return run(new Class<?>[] { primarySource }, args);
    }

 

 public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        //<2>我们先看构造函数初始化做了什么 <8>run启动
        return new SpringApplication(primarySources).run(args);
    }

<2>

 @SuppressWarnings({ "unchecked", "rawtypes" })
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        //我们的启动类指定的class 如:    SpringApplication.run(FinancialAnalysisApplication.class, args);
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //<3>获得环境类型
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //----------------------------<4>getSpringFactoriesInstances方法是在spring.factories找到实现了指定类型的类---------------------------
        /**
         * 获取BootstrapRegistryInitializer的实现类 默认没有实现
         */
        this.bootstrapRegistryInitializers = new ArrayList<>(
                getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
        /**
         * ApplicationContextInitializer 看spring-boot.jar包下的的默认配置有
         * org.springframework.context.ApplicationContextInitializer=\
         * org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
         * org.springframework.boot.context.ContextIdApplicationContextInitializer,\
         * org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
         * org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
         * org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
         */
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        /**
         *  ApplicationListener 看spring-boot.jar包下的的默认配置  后续由SpringApplicationRunListeners在各个时机委托给EVentPublishingRunListener 发送对应的Event事件 由以下监听器监听
         * # 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.DelegatingApplicationListener,\
         * org.springframework.boot.context.logging.LoggingApplicationListener,\
         * org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
         */
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //<7>这里主要是获取main方法进入的类型
        this.mainApplicationClass = deduceMainApplicationClass();
    }

<3>

org.springframework.boot.WebApplicationType#deduceFromClasspath

  private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
    private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
    private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
    private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
            "org.springframework.web.context.ConfigurableWebApplicationContext" };
    static WebApplicationType deduceFromClasspath() {
        //如果可以加载DispatcherHandler 同时WEBMVC_INDICATOR_CLASS JERSEY_INDICATOR_CLASS不存在则类型是REACTIVE
        if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
                && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
            //REACTIVE则是一种比较新的非阻塞的web框架,对应spring-webflux,需要启动支持reactive的web容器
            return WebApplicationType.REACTIVE;
        }
        //如果SERVLET_INDICATOR_CLASSES 都无法加载则是NoNE
        for (String className : SERVLET_INDICATOR_CLASSES) {
            if (!ClassUtils.isPresent(className, null)) {
                //NONE就是什么都没有,按照正常的代码走即可不需要额外启动web容器如tomcat等
                return WebApplicationType.NONE;
            }
        }
        //SERVLET则代表这是一个传统的servlet的web程序,对应SpringMVC 默认是SERVLET
        return WebApplicationType.SERVLET;
    }

<4>

org.springframework.boot.SpringApplication#getSpringFactoriesInstances

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
        return getSpringFactoriesInstances(type, new Class<?>[] {});
    }

 

 private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        //获得当前类的类加载器
        ClassLoader classLoader = getClassLoader();
        // <5>从spring.factories获取对应类型配置类的全名称
        Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        //反射创建
        List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        //如果打了@order注解 则根据@Order注解优先级排序返回
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

<5>

org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames

    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        //获取查找类型的名字后续通过他为key查找对应的类型
        String factoryTypeName = factoryType.getName();
        //<6>触发加载根据类型封装成map  然后通过factoryType去map获取对应的实现类配置的名字
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }

<6>

org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories

  public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        //先确定当前ClassLoader是否加载了配置 防止重复加载如果加载了直接返回加载后的map
        Map<String, List<String>> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }

        result = new HashMap<>();
        try {
            //获得所有META-INF/spring.factories下的配置
            Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
            //遍历加载各个url下的文件
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                //因为是properties格式配置所以转换为properties
                /**
                 * 如:
                 * org.springframework.boot.SpringApplicationRunListener=\
                 * org.springframework.boot.context.event.EventPublishingRunListener
                 */
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                //遍历封装到map
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
                    String factoryTypeName = ((String) entry.getKey()).trim();
                    String[] factoryImplementationNames =
                            StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
                    for (String factoryImplementationName : factoryImplementationNames) {
                        result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
                                .add(factoryImplementationName.trim());
                    }
                }
            }

            // 去重
            result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
                    .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
            //封装到cache 后续获取直接从cache获取
            cache.put(classLoader, result);
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
        return result;
    }

<7>

org.springframework.boot.SpringApplication#deduceMainApplicationClass

  private Class<?> deduceMainApplicationClass() {
        try {
            //获得当前执行堆栈
            StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
            //遍历知道获取main方法的入口堆栈 并获取类的class
            for (StackTraceElement stackTraceElement : stackTrace) {
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
            }
        }
        catch (ClassNotFoundException ex) {
            // Swallow and continue
        }
        return null;
    }

 <8>

org.springframework.boot.SpringApplication#run

public ConfigurableApplicationContext run(String... args) {
        //启动开始时间
        long startTime = System.nanoTime();
        //<9>创建DefaultBootstrapContext
        DefaultBootstrapContext bootstrapContext = createBootstrapContext();
        ConfigurableApplicationContext context = null;
        //设置java.awt.headless配置
        configureHeadlessProperty();
        //<10>获得监听器
        SpringApplicationRunListeners listeners = getRunListeners(args);
//调用starting 发送ApplicationStartingEvent事件 starting事件 listeners.starting(bootstrapContext,
this.mainApplicationClass); try { //封装系统变量 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //<11>加载环境变量 ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); //spring.beaninfo.ignore默认配置为true configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); //<13>通过ApplicationContextFactory创建Spring容器 context = createApplicationContext(); //容器状态设置 context.setApplicationStartup(this.applicationStartup); //<14>容器初始化前的相关配置 prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); //<16>调用容器的refresh方法 进入spring生命周期 refreshContext(context); //钩子方法 子类可以自定义实现 afterRefresh(context, applicationArguments); Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup); } //发送listeners的ApplicationStartedEvent事件 listeners.started(context, timeTakenToStartup); //<15>从容器中获得ApplicationRunner 和CommandLineRunner 完成回调 callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, listeners); throw new IllegalStateException(ex); } try { Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); listeners.ready(context, timeTakenToReady); } catch (Throwable ex) { handleRunFailure(context, ex, null); throw new IllegalStateException(ex); } return context; }

<9>

org.springframework.boot.SpringApplication#createApplicationContext

  private DefaultBootstrapContext createBootstrapContext() {
        DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
        //调用bootstrapRegistryInitializers我们可以做初始化配置
        this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
        return bootstrapContext;
    }

<10>

org.springframework.boot.SpringApplication#getRunListeners

rivate SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
        //根据getSpringFactoriesInstances 获取实现SpringApplicationRunListener接口 默认是EventpublishingRunListener 通过SpringApplicationRunListeners包装
        /**
         * # Run Listeners
         * org.springframework.boot.SpringApplicationRunListener=\
         * org.springframework.boot.context.event.EventPublishingRunListener 默认 可以持有当前application的引用 所以可以拿到listeners
* 发送时间则是由spring.factories applicationContextListener监听
*/ return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup); }

<11>

org.springframework.boot.SpringApplication#prepareEnvironment

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
                                                       DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
        // <12>根据环境初始化environment
        ConfigurableEnvironment environment = getOrCreateEnvironment();
        //将系统变量设置到environment
        configureEnvironment(environment, applicationArguments.getSourceArgs());
//<17>这里主要是将configurationProperties替换放到第一位 优先级最高 ConfigurationPropertySources.attach(environment);
//发送listener ApplicationEnviromentPreparedEvent 对应消费将触发我们application.yml配置文件加载 /** * # Run Listeners * org.springframework.boot.SpringApplicationRunListener=\ * org.springframework.boot.context.event.EventPublishingRunListener 默认 */ listeners.environmentPrepared(bootstrapContext, environment); DefaultPropertiesPropertySource.moveToEnd(environment); Assert.state(!environment.containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties."); bindToSpringApplication(environment); if (!this.isCustomEnvironment) { environment = convertEnvironment(environment); } ConfigurationPropertySources.attach(environment); return environment; }

<12>

org.springframework.boot.SpringApplication#getOrCreateEnvironment

private ConfigurableEnvironment getOrCreateEnvironment() {
        if (this.environment != null) {
            return this.environment;
        }
        switch (this.webApplicationType) {
            case SERVLET:
                return new ApplicationServletEnvironment();
            case REACTIVE:
                return new ApplicationReactiveWebEnvironment();
            default:
                return new ApplicationEnvironment();
        }
    }

<13>

com.biaoguoworks.sac.chains.commons.controller.ChainBaseController#createApplicationContext

    private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
    protected ConfigurableApplicationContext createApplicationContext() {
        return this.applicationContextFactory.create(this.webApplicationType);
    }

    ApplicationContextFactory DEFAULT = (webApplicationType) -> {
        try {
            switch (webApplicationType) {
                case SERVLET:
                    return new AnnotationConfigServletWebServerApplicationContext();
                case REACTIVE:
                    return new AnnotationConfigReactiveWebServerApplicationContext();
                default:
                    return new AnnotationConfigApplicationContext();
            }
        }
        catch (Exception ex) {
            throw new IllegalStateException("Unable create a default ApplicationContext instance, "
                    + "you may need a custom ApplicationContextFactory", ex);
        }
    };

<14>

org.springframework.boot.SpringApplication#prepareContext

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
                                ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
                                ApplicationArguments applicationArguments, Banner printedBanner) {
        //设置环境变量
        context.setEnvironment(environment);
//针对BeanNameGenerator resourceLoader、ConversionService设置缺省值 postProcessApplicationContext(context);
//触发ApplicationContextInitializer回调 也是从spring.factories获取 applyInitializers(context); //发送ApplicationContextInitializedEvent事件 listeners.contextPrepared(context); bootstrapContext.close(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof AbstractAutowireCapableBeanFactory) { ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences); if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // Load the sources Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty");
//source就是我们的启动类,这里主要是将我们的启动类的BeanDefintion加载到BeanFacotry,所以我们再启动类上打相关注解有效 load(context, sources.toArray(
new Object[0])); //发送ApplicationPreparedEvent事件 listeners.contextLoaded(context); }

<15>

org.springframework.boot.SpringApplication#callRunners

 private void callRunners(ApplicationContext context, ApplicationArguments args) {
        List<Object> runners = new ArrayList<>();
        //从容器中获得ApplicationRunner实现
        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
        //进行排序
        AnnotationAwareOrderComparator.sort(runners);
        //完成回调
        for (Object runner : new LinkedHashSet<>(runners)) {
            if (runner instanceof ApplicationRunner) {
                callRunner((ApplicationRunner) runner, args);
            }
            if (runner instanceof CommandLineRunner) {
                callRunner((CommandLineRunner) runner, args);
            }
        }
    }

<16>

    /**
     * 优雅关闭 
     * @param context
     */
    static final SpringApplicationShutdownHook shutdownHook = new SpringApplicationShutdownHook();
    private void refreshContext(ConfigurableApplicationContext context) {
        if (this.registerShutdownHook) {
            shutdownHook.registerApplicationContext(context);
        }
        refresh(context);
    }

 <17>

  private static final String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties";
    public static void attach(Environment environment) {
        Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
        //这只是一个门面 内部数组管理多个propertiesSource
        MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
        //获取configurationProperties
        PropertySource<?> attached = getAttached(sources);
        //如果存移除然后插入到头部
        if (attached != null && attached.getSource() != sources) {
            //移除
            sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
            attached = null;
        }
        //重新放入头部通过ConfigurationPropertySourcesPropertySource 包装 这个内部管理多个SpringConfigurationPropertySources 同时也是根据SpringConfigurationPropertySources包装了一层
        if (attached == null) {
            sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
                    new SpringConfigurationPropertySources(sources)));
        }
    }

 

posted @ 2022-02-25 11:19  意犹未尽  阅读(227)  评论(0编辑  收藏  举报