SpringBoot启动流程

定义启动类

@EnableFeignClients
@EnableDiscoveryClient
@EnableTransactionManagement
@SpringBootApplication
public class CDAApplication extends SpringBootServletInitializer {

    public static void main(String[] args){
        System.setProperty("spring.devtools.restart.enabled", "false");
        SpringApplication.run(CDAApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {

        // 注意这里要指向原先用main方法执行的Application启动类
        return builder.sources(CDAApplication.class);
    }

}

SpringApplication

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
}

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//初始化SpringApplication
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//指定当前应用类型WebApplicationType 这里是 1 (WebApplicationType.SERVLET)
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		//向容器中注册BootstrapRegistryInitializer
		//BootstrapRegistryInitializer作用:在应用启动时初始化的对象和配置
       //BootstrapRegistryInitializer一般和SpringApplicationRunListeners一起使用
		this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
		//向容器中注册ApplicationContextInitializer
		//ApplicationContextInitializer作用:在创建Spring应用上下文时初始化一些配置,比如向系统环境添加一些配置
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//向容器中注册ApplicationListener
		//ApplicationListener 作用:监听各种应用事件,以便在事件发生时执行相应的逻辑
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		//指定主程序类
		this.mainApplicationClass = deduceMainApplicationClass();
}
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();
		//从配置文件中以type为key,拿到对应的所有value值
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		//通过反射构造方法实例化bean
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		//最后进行排序
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

	@SuppressWarnings("unchecked")
	private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
			ClassLoader classLoader, Object[] args, Set<String> names) {
		List<T> instances = new ArrayList<>(names.size());
		for (String name : names) {
			try {
				Class<?> instanceClass = ClassUtils.forName(name, classLoader);
				Assert.isAssignable(type, instanceClass);
				Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
				T instance = (T) BeanUtils.instantiateClass(constructor, args);
				instances.add(instance);
			}
			catch (Throwable ex) {
				throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
			}
		}
		return instances;
	}
public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		//创建一个默认的引导启动类上下文
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		//设置一些系统配置
		configureHeadlessProperty();
		//获取所有的SpringApplicationRunListeners 
		//用于监听和响应应用启动和运行事件
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//开始监听应用启动
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
		//封装启动指定的参数
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			//准备系统环境变量
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			//配置一些系统环境变量
			configureIgnoreBeanInfo(environment);
			//打印应用启动Banner
			Banner printedBanner = printBanner(environment);
			//实例化应用上下文(根据webApplicationType的值确定)
			//就是AnnotationConfigServletWebServerApplicationContext
			context = createApplicationContext();
			//用于记录日志(比如状态,时间等等)
	        context.setApplicationStartup(this.applicationStartup);
	        //准备刷新容器
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			//开始刷新容器
			refreshContext(context);
			//刷新容器之后,留给子类扩展
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			//容器已启动
			listeners.started(context);
			//回调执行各种事件
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}

		try {
		//系统正在运行中
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
public interface ApplicationContextFactory {

	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);
		}
	};
}
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
		//设置容器的环境
		context.setEnvironment(environment);
		//设置容器需要的一些资源
		postProcessApplicationContext(context);
		//执行ApplicationContextInitializer.initialize方法
		applyInitializers(context);
		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 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");
		load(context, sources.toArray(new Object[0]));
		listeners.contextLoaded(context);
	}
private void refreshContext(ConfigurableApplicationContext context) {
		if (this.registerShutdownHook) {
			shutdownHook.registerApplicationContext(context);
		}
		//真正刷新容器
		refresh(context);
	}
//用于在应用启动之后执行特定的接口逻辑
//比如数据初始化、配置文件加载、与外部系统交互等
private void 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);
			}
		}
	}

你可能感兴趣的:(sprinboot,java,spring,boot,后端,java)