最新公告
  • 欢迎您光临极客文库,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • 1 实例化SpringApplication
    SpringApplication.run(BootifulApplication.class, args);
    publicstatic ConfigurableApplicationContext run(Class<?> primarySource,String... args) {return run(newClass<?>[] { primarySource }, args);}
    publicstatic ConfigurableApplicationContext run(Class<?>[] primarySources,String[] args) {returnnew SpringApplication(primarySources).run(args); //new SpringApplication}
    publicSpringApplication(Class<?>... primarySources) {this(null, primarySources);}
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {//设置资源加载器为nullthis.resourceLoader = resourceLoader;//断言加载资源类不能为nullAssert.notNull(primarySources, "PrimarySources must not be null");//将primarySources数组转换为List,最后放到LinkedHashSet集合中this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//【1.1 推断当前应用类型是否为WEB】this.webApplicationType = WebApplicationType.deduceFromClasspath();//【1.2 设置应用上下文初始化器】setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class));//【1.3 设置监听器】setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//【1.4 推断应用的入口类】this.mainApplicationClass = deduceMainApplicationClass();}

    1.1 推断当前应用类型是否为WEB

    根据classpath下的内容推断出应用的类型
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    static WebApplicationType deduceFromClasspath() {if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {return WebApplicationType.REACTIVE; }for (String className : SERVLET_INDICATOR_CLASSES) {if (!ClassUtils.isPresent(className, null)) {return WebApplicationType.NONE; } }return WebApplicationType.SERVLET;}

    1.2 设置应用上下文初始化器

    setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
    • ApplicationContextInitializer
    publicinterfaceApplicationContextInitializer<CextendsConfigurableApplicationContext> {/** * Initialize the given application context. * @param applicationContext the application to configure */voidinitialize(C applicationContext);}
    • getSpringFactoriesInstances(ApplicationContextInitializer.class)
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {return getSpringFactoriesInstances(type, newClass<?>[] {});}
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {//获取当前上下文类加载器 ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicates//获取ApplicationContextInitializer实例名称并且去重 Set<String> names = new LinkedHashSet<>(//进入loadFactoryNames方法并且找到loadSpringFactories---spring.factories SpringFactoriesLoader.loadFactoryNames(type, classLoader));//创建初始化器实例列表 List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);//排序 AnnotationAwareOrderComparator.sort(instances);return instances;}
    • setInitializers(…)
    初始化一个ApplicationContextInitializer
    publicvoidsetInitializers( Collection<? extends ApplicationContextInitializer<?>> initializers) {this.initializers = new ArrayList<>();this.initializers.addAll(initializers);}

    1.3 设置监听器

    setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
    • ApplicationListener
    publicinterfaceApplicationListener<EextendsApplicationEvent> extendsEventListener{/** * Handle an application event. * @param event the event to respond to */voidonApplicationEvent(E event);}
    • getSpringFactoriesInstances(ApplicationListener.class)
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {return getSpringFactoriesInstances(type, newClass<?>[] {});}
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {//获取当前上下文类加载器 ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicates//获取ApplicationContextInitializer实例名称并且去重 Set<String> names = new LinkedHashSet<>(//进入loadFactoryNames方法并且找到loadSpringFactories---spring.factories SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);//创建初始化器实例列表 AnnotationAwareOrderComparator.sort(instances);//排序return instances;}
    • setListeners(…)
    初始化一个ApplicationListener
    publicvoidsetListeners(Collection<? extends ApplicationListener<?>> listeners) {this.listeners = new ArrayList<>();this.listeners.addAll(listeners);}

    1.4 推断应用的入口类

    this.mainApplicationClass = deduceMainApplicationClass();
    private Class<?> deduceMainApplicationClass() {try {//构造一个运行时异常,遍历异常栈中的方法名,获取方法名为main的栈帧,得到入口类的名字再返回该类 StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())) {return Class.forName(stackTraceElement.getClassName()); } } }catch (ClassNotFoundException ex) {// Swallow and continue }returnnull;}

    2 调用run方法

    /** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @return a running {@link ApplicationContext}*/public ConfigurableApplicationContext run(String... args){//创建计时类StopWatch stopWatch = new StopWatch();stopWatch.start();//初始化应用上下文和异常报告集合ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();//设置headless属性configureHeadlessProperty();//【2.1 创建运行监听器】SpringApplicationRunListeners listeners = getRunListeners(args);//发布应用启动事件listeners.starting();try {//初始化默认应用参数类 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args);//【2.2 根据监听器和应用参数类准备Spring环境】 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment);//创建Banner打印类 Banner printedBanner = printBanner(environment);//【2.3 创建应用上下文】 context = createApplicationContext();//准备异常报告 exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//【2.4 准备应用上下文】 prepareContext(context, environment, listeners, applicationArguments, printedBanner);//【2.5 刷新应用上下文】 refreshContext(context);//应用上下文后置处理刷新 afterRefresh(context, applicationArguments);//停止计时类 stopWatch.stop();//输出日志记录执行主类名、时间信息if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); }//发布应用上下文启动完成事件 listeners.started(context);//【2.6 执行Runner运行器】 callRunners(context, applicationArguments);}catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners);thrownew IllegalStateException(ex);}try {//发布应用上下文就绪事件 listeners.running(context);}catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null);thrownew IllegalStateException(ex);}//返回应用上下文return context;}

    2.1 创建运行监听器

    SpringApplicationRunListeners listeners = getRunListeners(args);
    private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args));}
    • SpringApplicationRunListener
    org.springframework.boot:spring-boot/META-INF/spring.factories
    • getSpringFactoriesInstances(…)

    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<>( SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances);return instances;}
    • new SpringApplicationRunListeners(…)
    SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {this.log = log;this.listeners = new ArrayList<>(listeners);}

    2.2 根据监听器和应用参数类准备Spring环境

    ConfigurableEnvironment environment = prepareEnvironment(listeners,       applicationArguments);
    private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {// Create and configure the environment//获取应用环境(3种情况) ConfigurableEnvironment environment = getOrCreateEnvironment();//配置应用环境 configureEnvironment(environment, applicationArguments.getSourceArgs()); listeners.environmentPrepared(environment); bindToSpringApplication(environment);if (!this.isCustomEnvironment) { environment = new EnvironmentConverter(getClassLoader()) .convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } ConfigurationPropertySources.attach(environment);return environment;}

    2.3 创建应用上下文

    context = createApplicationContext();
    protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {try {switch (this.webApplicationType) {case SERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);break;case REACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);break;default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } }catch (ClassNotFoundException ex) {thrownew IllegalStateException("Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass", ex); } }return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);}

    2.4 准备应用上下文

    prepareContext(context, environment, listeners, applicationArguments,         printedBanner);
    private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {//绑定环境到上下文 context.setEnvironment(environment);//配置上下文的bean生成器和资源加载器 postProcessApplicationContext(context);//为上下文采用所有初始化器 applyInitializers(context);//触发监听器的contextPrepared事件 listeners.contextPrepared(context);//记录启动日志if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); }// Add boot specific singleton beans//注册两个特殊的单例Bean ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); }if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); }// Load the sources//加载所有资源Set<Object> sources = getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(newObject[0]));//触发监听器的contextLoaded事件 listeners.contextLoaded(context);}

    2.5 刷新应用上下文

    refreshContext(context);
    privatevoidrefreshContext(ConfigurableApplicationContext context) { refresh(context); //--->进入该方法if (this.registerShutdownHook) {try { context.registerShutdownHook(); }catch (AccessControlException ex) {// Not allowed in some environments. } }}
    protectedvoidrefresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); //--->进入该方法}
    publicvoidrefresh()throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.//context:启动日期|设置context当前状态|初始化环境|验证必须 prepareRefresh();
    // Tell the subclass to refresh the internal bean factory.//刷新内部bean工厂,即创建一个bean工厂(对BeanDefinition的定义、解析、处理和注册) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // Prepare the bean factory for use in this context.//上面创建好了之后,还需要配置一些东西才能使用 prepareBeanFactory(beanFactory);
    try {// Allows post-processing of the bean factory in context subclasses.//注册WEB特性的scope(如request,session等) postProcessBeanFactory(beanFactory);
    // Invoke factory processors registered as beans in the context.//调用所有的bean工厂处理器对bean进行一些处理 invokeBeanFactoryPostProcessors(beanFactory);
    // Register bean processors that intercept bean creation.//注册用来拦截bean registerBeanPostProcessors(beanFactory);
    // Initialize message source for this context.//主要用于国际化 initMessageSource();
    // Initialize event multicaster for this context.//为context初始化一个事件广播器 initApplicationEventMulticaster();
    // Initialize other special beans in specific context subclasses./* 在AbstractApplicationContext的子类中初始化其他特殊的bean。 其实就是初始化ThemeSource接口的实例。这个方法需要在所有单例bean初始化之前调用。 */ onRefresh();
    // Check for listener beans and register them.//注册应用监听器 registerListeners();
    // Instantiate all remaining (non-lazy-init) singletons.//完成对bean工厂初始化工作 finishBeanFactoryInitialization(beanFactory);
    // Last step: publish corresponding event.//调用LifecycleProcessor的onRefresh()方法并且发布事件 finishRefresh(); }
    catch (BeansException ex) {if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex); }
    // Destroy already created singletons to avoid dangling resources. destroyBeans();
    // Reset 'active' flag. cancelRefresh(ex);
    // Propagate exception to caller.throw ex; }
    finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore... resetCommonCaches(); } }}

    2.6 执行Runner运行器

    callRunners(context, applicationArguments);
    执行所有ApplicationRunner和CommandLineRunner两种运行器
    privatevoid callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<>(); 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); } }}
    本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
    极客文库 » 这样深度Spring Boot的源码解析,看完帮你立即提升一个台阶!

    常见问题FAQ

    如果资源链接失效了怎么办?
    本站用户分享的所有资源都有自动备份机制,如果资源链接失效,请联系本站客服QQ:2580505920更新资源地址。
    如果用户分享的资源与描述不符怎么办?
    可以联系客服QQ:2580505920,如果要求合理可以安排退款或者退赞助积分。
    如何分享个人资源获取赞助积分或其他奖励?
    本站用户可以分享自己的资源,但是必须保证资源没有侵权行为。点击个人中心,根据操作填写并上传即可。资源所获收益完全归属上传者,每周可申请提现一次。
    如果您发现了本资源有侵权行为怎么办?
    及时联系客服QQ:2580505920,核实予以删除。

    Leave a Reply

    Hi, 如果你对这款资源有疑问,可以跟我联系哦!

    联系发布者

    Leave a Reply

    Hi, 如果你对这款资源有疑问,可以跟我联系哦!

    联系发布者
    • 101会员总数(位)
    • 3672资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 124稳定运行(天)

    欢迎加入「极客文库」,成为原创作者从这里开始!

    立即加入 了解更多
    成为赞助用户享有更多特权立即升级