SpringBoot2.0源码三

第三章:理解SpringApplication

第一节:基础技术和衍生技术

学好spirngboot,一定要学好spring framework

基础技术(spring framework)
  • spring 模式注解
  • spirng 应用上下文
  • spring 工厂加载机制
  • spring 应用上下文初始器
  • spring Environment 抽象接口
  • spirng 应用事件/监听器
衍生技术(spring boot )
  • SpringApplication
  • SpringApplication Builder API
  • SpringApplication 运行监听器
  • SpringApplication 参数
  • SpringApplication 故障分析
  • Spring Boot 应用事件/监听器

第二节:SpringApplication 准备阶段

定义
  • spring应用引导类,提供便利的自定义行为方法
场景
  • 嵌入式web应用和非web应用(非嵌入式web server则失效,现在版本不知道支持不)
运行
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}
自定义SpringApplication
  • 通过SpringApplicationBuilder 调整

    public class MyApplication {
    
        public static void main(String[] args) {
            new SpringApplicationBuilder()
            .sources(ApplicationBoot.class)//这样配置源,不一定是主方法,但是其他方式必须是@SpringBoot
            .run(args);
        }
        
        @SpringBootApplication
        public static class ApplicationBoot{   
        }
    }
    
准备阶段
//SpringApplication 构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
    	//配置spring bean源
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    	//推断web应用类型
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
    	//加载应用上下文
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    	//加载应用事件监听器
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    	//推断主引导类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

1. 配置spring bean源
  • java配置class或者xml上下文配置文件集合,用于Spring Boot BeanDefinitionLoader 读取,并且将配置源解析加载为spring bean 定义,可以一个或多个以上
1. java配置class
  • 用于spring 注解驱动中java配置类,大多数情况下是spring模式注解所标注的类,如@Configuration
2. xml上下文配置文件
  • 用于spring 传统配置驱动中的xml文件
2. 推断deduce
  • 推断web应用类型,根据当前应用classpath中是否存在相关实现类,来推断

    • Web Reactive : WebApplicationType.REACTIVE
    • Web Servlet : WebApplicationType.SERVLET
    • 非Web : WebApplicationType.NONE
    #spring-boot-2.3.2
    private WebApplicationType deduceWebApplicationType() {
    		if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
    				&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)
    				&& !ClassUtils.isPresent(JERSEY_WEB_ENVIRONMENT_CLASS, null)) {
    			return WebApplicationType.REACTIVE;
    		}
    		for (String className : WEB_ENVIRONMENT_CLASSES) {
    			if (!ClassUtils.isPresent(className, null)) {
    				return WebApplicationType.NONE;
    			}
    		}
    		return WebApplicationType.SERVLET;
    	}
    
    private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
    			"org.springframework.web.context.ConfigurableWebApplicationContext" };
    
    
  • 推断主引导类(Main Class)就是@SpringBootApplication注解的类,根据Main线程执行堆栈判断实际的引导类

    heap 堆
    stack栈
    private Class<?> deduceMainApplicationClass() {
        try {
            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
        }
        return null;
    }
    
    
3. 加载
  • 加载应用上下文初始器 ApplicationContextInitializer

    • 利用spring工程加载机制,实例化ApplicationContextInitializer实现类,并排序对象集合

      private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
      		ClassLoader classLoader = getClassLoader();
      		// Use names and ensure unique to protect against duplicates
          	//spring工厂类加载器
          	//第一步:实现,加载实现类
      		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
      		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
              //第三步:排序
      		AnnotationAwareOrderComparator.sort(instances);
      		return instances;
      }
      
      //spring工厂类加载器
      public final class SpringFactoriesLoader {
      
      	/**
      	 * The location to look for factories.
      	 * <p>Can be present in multiple JAR files.
      	 */
          //第二步:配置资源
      	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
      
      
      	private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
      
      	private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
      }
      
      #spring-boot-autoconfigure-2.3.3.RELEASE.jar!/META-INF/spring.factories
      # Initializers 初始化器
      #应用上下文初始化器
      org.springframework.context.ApplicationContextInitializer=\
      org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
      org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
      
      # Application Listeners
      org.springframework.context.ApplicationListener=\
      org.springframework.boot.autoconfigure.BackgroundPreinitializer
      
      # Auto Configuration Import Listeners
      org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
      org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
      
      
  • 加载应用事件监听器 ApplicationListener

    • 具体步骤同上

第三节:SpringApplication 运行阶段

1. 加载SpringApplication 运行监听器SpringApplicationRunListeners
  • 利用spring工厂加载机制,读取SpringApplicationRunListener 对象集合,并且封装到组合类SpringApplicationRunListeners
@SpringBootApplication
public class LCApplication {
    public static void main(String[] args) {
        SpringApplication.run(LCApplication.class, args);
    }
}
//run()方法
public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
    	//1-加载运行监视器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
    	//2-运行监视器
        listeners.starting();

        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //3-创建environment,见下文创建spring environment
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            //4-创建spirng应用上下文,见下文创建spring应用上下文
            context = this.createApplicationContext();
            
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }
    }
//工厂类加载  
private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    }
2. 运行SpringApplication运行监听器SpringApplicationRunListeners
  • SpringApplicationRunListeners 监听多个运行状态方法
监听方法阶段说明springboot起始版本
starting()spring应用刚启动1.0
environmentPrepared(ConfigurableEnvironment)ConfigurableEnvironment准备妥当,允许将其调整1.0
contextPrepared(ConfigurableApplicationContext)ConfigurableApplicationContext准备妥当,允许将其调整1.0
contextLoaded(ConfigurableApplicationContext)ConfigurableApplicationContext已加载,但仍未启动1.0
started(ConfigurableApplicationContext)ConfigurableApplicationContext已启动,此时spring bean已初始化完成2.0
running(ConfigurableApplicationContext)spring应用正在运行2.0
failed(ConfigurableApplicationContext,Throwable)spring应用运行失败2.0
//org.springframework.boot.SpringApplicationRunListeners
class SpringApplicationRunListeners {
    private final Log log;
    private final List<SpringApplicationRunListener> listeners;

    SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
        this.log = log;
        this.listeners = new ArrayList(listeners);
    }

    void starting() {
        Iterator var1 = this.listeners.iterator();

        while(var1.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var1.next();
            listener.starting();
        }

    }

    void environmentPrepared(ConfigurableEnvironment environment) {
        Iterator var2 = this.listeners.iterator();

        while(var2.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
            listener.environmentPrepared(environment);
        }

    }

    void contextPrepared(ConfigurableApplicationContext context) {
        Iterator var2 = this.listeners.iterator();

        while(var2.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
            listener.contextPrepared(context);
        }

    }

    void contextLoaded(ConfigurableApplicationContext context) {
        Iterator var2 = this.listeners.iterator();

        while(var2.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
            listener.contextLoaded(context);
        }

    }

    void started(ConfigurableApplicationContext context) {
        Iterator var2 = this.listeners.iterator();

        while(var2.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
            listener.started(context);
        }

    }

    void running(ConfigurableApplicationContext context) {
        Iterator var2 = this.listeners.iterator();

        while(var2.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
            listener.running(context);
        }

    }

    void failed(ConfigurableApplicationContext context, Throwable exception) {
        Iterator var3 = this.listeners.iterator();

        while(var3.hasNext()) {
            SpringApplicationRunListener listener = (SpringApplicationRunListener)var3.next();
            this.callFailedListener(listener, context, exception);
        }

    }
}

3. 监听spring boot 事件/spring 事件
spring Framework 事件/监听器编程模型
  • spring 应用事件
    • 普通应用事件 Application
    • 应用上下文事件:ApplicationContextEvent
  • spring 应用监听器
    • 接口编程模型: ApplicationListener
    • 注解编程模型:@EventListener
  • spring 应用事件广播器
    • 接口:ApplicationEventMulticaster
    • 实现类:SimpleApplicationEventMulticaster
      • 执行模式:同步或异步
EventPublishingRunListener 监听方法与 spring boot 事件对应关系
监听方法springboot事件springboot起始版本
starting()ApplicationStartingEvent1.5
environmentPrepared(ConfigurableEnvironment)ApplicationEnvironmentPreparedEvent1.0
`contextPrepared(ConfigurableApplicationContext)
contextLoaded(ConfigurableApplicationContext)ApplicationPerparedEvent1.0
started(ConfigurableApplicationContext)ApplicationStartedEvent2.0
running(ConfigurableApplicationContext)ApplicationReadyEvent2.0
failed(ConfigurableApplicationContext,Throwable)ApplicationFailedEvent1.0
//org.springframework.boot.context.event.EventPublishingRunListener
//注意这里,实现了SpringApplicationRunListener接口
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    private final SpringApplication application;
    private final String[] args;
    private final SimpleApplicationEventMulticaster initialMulticaster;
	//这里构造器中的参数,为入口类传入的参数
    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        this.initialMulticaster = new SimpleApplicationEventMulticaster();
        Iterator var3 = application.getListeners().iterator();

        while(var3.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var3.next();
            this.initialMulticaster.addApplicationListener(listener);
        }

    }

    public int getOrder() {
        return 0;
    }

    public void starting() {
        //广播器
        this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    }

    public void environmentPrepared(ConfigurableEnvironment environment) {
        this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
    }

    public void contextPrepared(ConfigurableApplicationContext context) {
        this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
    }

    public void contextLoaded(ConfigurableApplicationContext context) {
        ApplicationListener listener;
        for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {
            listener = (ApplicationListener)var2.next();
            if (listener instanceof ApplicationContextAware) {
                ((ApplicationContextAware)listener).setApplicationContext(context);
            }
        }

        this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
    }

    public void started(ConfigurableApplicationContext context) {
        context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
        AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
    }

    public void running(ConfigurableApplicationContext context) {
        context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
        AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
    }

    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
        if (context != null && context.isActive()) {
            context.publishEvent(event);
        } else {
            if (context instanceof AbstractApplicationContext) {
                Iterator var4 = ((AbstractApplicationContext)context).getApplicationListeners().iterator();

                while(var4.hasNext()) {
                    ApplicationListener<?> listener = (ApplicationListener)var4.next();
                    this.initialMulticaster.addApplicationListener(listener);
                }
            }

            this.initialMulticaster.setErrorHandler(new EventPublishingRunListener.LoggingErrorHandler());
            this.initialMulticaster.multicastEvent(event);
        }

    }
}

4. 创建spring应用上下文 ConfigurableApplicationContext

根据准备阶段的推断Web应用类型,创建对应的ConfigurableApplicationContext实例

  • web reactive : AnnotationConfigReactiveWebServerApplicatioinContext
  • web servlet : AnnotationConfigServletWebServerApplicationContext
  • 非web : AnnotationConfigApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
        try {
            switch(this.webApplicationType) {
            case SERVLET:
                contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                break;
            case REACTIVE:
                contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                break;
            default:
                contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
            }
        } catch (ClassNotFoundException var3) {
            throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
        }
    }

    return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
5. 创建Environment

根据准备阶段的推断Web应用类型,创建对应的ConfigurableEnvironment实例

  • web reactive : StandardEnvironment
  • web servlet : StandardServletEnvironment
  • 非web : StandardEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    } else {
        switch(this.webApplicationType) {
        case SERVLET:
            return new StandardServletEnvironment();
        case REACTIVE:
            return new StandardReactiveWebEnvironment();
        default:
            return new StandardEnvironment();
        }
    }
}
6. 故障报告
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值