SpringBoot2 | SpringBoot启动流程源码分析(一)

 

会员中心

收藏

动态

消息

创作中心

SpringBoot2 | SpringBoot启动流程源码分析(一)

置顶 张书康 2018-08-31 15:29:58  73428  收藏 388

分类专栏: SpringBoot Spring springmvc 文章标签: SpringBoot2

版权

微信公众号:吉姆餐厅ak
学习更多源码知识,欢迎关注。
在这里插入图片描述


SpringBoot2 | SpringBoot启动流程源码分析(一)

SpringBoot2 | SpringBoot启动流程源码分析(二)

SpringBoot2 | @SpringBootApplication注解 自动化配置流程源码分析(三)

SpringBoot2 | SpringBoot Environment源码分析(四)

SpringBoot2 | SpringBoot自定义AutoConfiguration | SpringBoot自定义starter(五)

SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

SpringBoot2 | 条件注解@ConditionalOnBean原理源码深度解析(七)

SpringBoot2 | Spring AOP 原理源码深度剖析(八)

SpringBoot2 | SpingBoot FilterRegistrationBean 注册组件 | FilterChain 责任链源码分析(九)

SpringBoot2 | BeanDefinition 注册核心类 ImportBeanDefinitionRegistrar (十)

SpringBoot2 | Spring 核心扩展接口 | 核心扩展方法总结(十一)


概述:

前阵子看到了SpringCloud社区的一个开源项目,主要是对服务发现增强的功能。研究项目的时候发现代码简练,优雅,最主要是spring ioc和aop特性应用的得心应手。若非对源码有深入研究,不可能写出这么优秀的开源项目。另外在现有的springboot专栏中,大多数博文旨在应用,对一些中间件的整合之类,源码分析的博客数量有限。鉴于以上两方面,该系列应运而生。

该系列主要还是Spring的核心源码,不过目前Springboot大行其道,所以就从Springboot开始分析。最新版本是Springboot2.0.4,Spring5,所以新特性本系列后面也会着重分析。

整个系列会围绕springboot启动流程进行源码分析,在整个流程中,会遇到一些核心类或者核心流程,会着重讲解,所以篇幅可能会增多,做好准备。


源码分析

首先是项目启动类:

	public static void main(String[] args) {
		SpringApplication.run(MarsApplication.class, args);
	}
  • 1
  • 2
  • 3
	public SpringApplication(Object... sources) {
		//初始化
		initialize(sources);
	}
  • 1
  • 2
  • 3
  • 4

初始化时,会先进行区分环境:非web环境、web环境、reactive环境三种。如下:

	private void initialize(Object[] sources) {
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
		//设置servlet环境
		this.webEnvironment = deduceWebEnvironment();
		//获取ApplicationContextInitializer,也是在这里开始首次加载spring.factories文件
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		//获取监听器,这里是第二次加载spring.factories文件
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

来看一下具体环境判断的deduceWebEnvironment()方法:

	private WebApplicationType deduceWebApplicationType() {
		if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
				&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {
			return WebApplicationType.REACTIVE;
		}
		for (String className : WEB_ENVIRONMENT_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里主要是通过判断REACTIVE相关的字节码是否存在,如果不存在,则web环境即为SERVLET类型。这里设置好web环境类型,在后面会根据类型初始化对应环境。

ApplicationContextInitializer是spring组件spring-context组件中的一个接口,主要是spring ioc容器刷新之前的一个回调接口,用于处于自定义逻辑。

上述代码中getSpringFactoriesInstances方法会加载META-INF/spring.factories文件,spring.factories文件中的默认的实现类如下:

这里写图片描述

这里监听器为9个:

# 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.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

还有1个为:org.springframework.boot.autoconfigure.BackgroundPreinitializer
这10个监听器会贯穿springBoot整个生命周期。稍后会介绍。


这里先继续后面的流程。来看一下run方法:

public ConfigurableApplicationContext run(String... args) {
		//时间监控
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//java.awt.headless是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true,系统变量默认为true
		configureHeadlessProperty();
		//获取spring.factories中的监听器变量,args为指定的参数数组,默认为当前类SpringApplication
		//第一步:获取并启动监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			//第二步:构造容器环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			//设置需要忽略的bean
			configureIgnoreBeanInfo(environment);
			//打印banner
			Banner printedBanner = printBanner(environment);
			//第三步:创建容器
			context = createApplicationContext();
			//第四步:实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//第五步:准备容器
			prepareContext(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, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 第一步:获取并启动监听器
  • 第二步:构造容器环境
  • 第三步:创建容器
  • 第四步:实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
  • 第五步:准备容器
  • 第六步:刷新容器
  • 第七步:刷新容器后的扩展接口

下面具体分析。


一:获取并启动监听器

1)获取监听器

SpringApplicationRunListeners listeners = getRunListeners(args);
跟进getRunListeners方法:

	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
				SpringApplicationRunListener.class, types, this, args));
	}
  • 1
  • 2
  • 3
  • 4
  • 5

上面可以看到,args本身默认为空,但是在获取监听器的方法中,getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)将当前对象作为参数,该方法用来获取spring.factories对应的监听器:

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
  • 1
  • 2
  • 3

整个 springBoot 框架中获取factories的方式统一如下:

	@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文件到内存
				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;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

上面通过反射获取实例时会触发EventPublishingRunListener的构造函数:

	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

重点来看一下addApplicationListener方法:

	@Override
	public void addApplicationListener(ApplicationListener<?> listener) {
		synchronized (this.retrievalMutex) {
			// Explicitly remove target for a proxy, if registered already,
			// in order to avoid double invocations of the same listener.
			Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
			if (singletonTarget instanceof ApplicationListener) {
				this.defaultRetriever.applicationListeners.remove(singletonTarget);
			}
			//内部类对象
			this.defaultRetriever.applicationListeners.add(listener);
			this.retrieverCache.clear();
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

上述方法定义在SimpleApplicationEventMulticaster父类AbstractApplicationEventMulticaster中。关键代码为this.defaultRetriever.applicationListeners.add(listener);,这是一个内部类,用来保存所有的监听器。也就是在这一步,将spring.factories中的监听器传递到SimpleApplicationEventMulticaster中。
继承关系如下:
这里写图片描述

2)启动监听器:

listeners.starting();,获取的监听器为EventPublishingRunListener,从名字可以看出是启动事件发布监听器,主要用来发布启动事件。

	@Override
	public void starting() {
	//关键代码,这里是创建application启动事件`ApplicationStartingEvent`
		this.initialMulticaster.multicastEvent(
				new ApplicationStartingEvent(this.application, this.args));
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

EventPublishingRunListener这个是springBoot框架中最早执行的监听器,在该监听器执行started()方法时,会继续发布事件,也就是事件传递。这种实现主要还是基于spring的事件机制。
继续跟进SimpleApplicationEventMulticaster,有个核心方法:

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			//获取线程池,如果为空则同步处理。这里线程池为空,还未没初始化。
			Executor executor = getTaskExecutor();
			if (executor != null) {
			    //异步发送事件
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				//同步发送事件
				invokeListener(listener, event);
			}
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这里会根据事件类型ApplicationStartingEvent获取对应的监听器,在容器启动之后执行响应的动作,有如下4种监听器:
这里写图片描述
这是springBoot启动过程中,第一处根据类型,执行监听器的地方。根据发布的事件类型从上述10种监听器中选择对应的监听器进行事件发布,当然如果继承了 springCloud或者别的框架,就不止10个了。这里选了一个 springBoot 的日志监听器来进行讲解,核心代码如下:

 @Override
    public void onApplicationEvent(ApplicationEvent event) {
        //在springboot启动的时候
        if (event instanceof ApplicationStartedEvent) {
            onApplicationStartedEvent((ApplicationStartedEvent) event);
        }
        //springboot的Environment环境准备完成的时候
        else if (event instanceof ApplicationEnvironmentPreparedEvent) {
            onApplicationEnvironmentPreparedEvent(
                    (ApplicationEnvironmentPreparedEvent) event);
        }
        //在springboot容器的环境设置完成以后
        else if (event instanceof ApplicationPreparedEvent) {
            onApplicationPreparedEvent((ApplicationPreparedEvent) event);
        }
        //容器关闭的时候
        else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event)
                .getApplicationContext().getParent() == null) {
            onContextClosedEvent();
        }
        //容器启动失败的时候
        else if (event instanceof ApplicationFailedEvent) {
            onApplicationFailedEvent();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

因为我们的事件类型为ApplicationEvent,所以会执行onApplicationStartedEvent((ApplicationStartedEvent) event);。springBoot会在运行过程中的不同阶段,发送各种事件,来执行对应监听器的对应方法。大同小异,别的监听器执行流程这里不再赘述,后面会有单独的详解。
继续后面的流程。


二:环境构建:

ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
跟进去该方法:

	private ConfigurableEnvironment prepareEnvironment(
			SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		//获取对应的ConfigurableEnvironment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		//配置
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		//发布环境已准备事件,这是第二次发布事件
		listeners.environmentPrepared(environment);
		bindToSpringApplication(environment);
		if (this.webApplicationType == WebApplicationType.NONE) {
			environment = new EnvironmentConverter(getClassLoader())
					.convertToStandardEnvironmentIfNecessary(environment);
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

来看一下getOrCreateEnvironment()方法,前面已经提到,environment已经被设置了servlet类型,所以这里创建的是环境对象是StandardServletEnvironment

	private ConfigurableEnvironment getOrCreateEnvironment() {
		if (this.environment != null) {
			return this.environment;
		}
		if (this.webApplicationType == WebApplicationType.SERVLET) {
			return new StandardServletEnvironment();
		}
		return new StandardEnvironment();
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

枚举类WebApplicationType是springBoot2新增的特性,主要针对spring5引入的reactive特性。枚举类型如下:

public enum WebApplicationType {
	//不需要再web容器的环境下运行,普通项目
	NONE,
	//基于servlet的web项目
	SERVLET,
	//这个是spring5版本开始的新特性
	REACTIVE
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Environment接口提供了4种实现方式,StandardEnvironmentStandardServletEnvironmentMockEnvironmentStandardReactiveWebEnvironment,分别代表普通程序、Web程序、测试程序的环境、响应式web环境,具体后面会详细讲解。
这里只需要知道在返回return new StandardServletEnvironment();对象的时候,会完成一系列初始化动作,主要就是将运行机器的系统变量和环境变量,加入到其父类AbstractEnvironment定义的对象MutablePropertySources中,MutablePropertySources对象中定义了一个属性集合:

private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<PropertySource<?>>();
  • 1

执行到这里,系统变量和环境变量已经被载入到配置文件的集合中,接下来就行解析项目中的配置文件。

来看一下listeners.environmentPrepared(environment);,上面已经提到了,这里是第二次发布事件。什么事件呢?
顾名思义,系统环境初始化完成的事件。
发布事件的流程上面已经讲过了,这里不在赘述。来看一下根据事件类型获取到的监听器:
这里写图片描述

可以看到获取到的监听器和第一次发布启动事件获取的监听器有几个是重复的,这也验证了监听器是可以多次获取,根据事件类型来区分具体处理逻辑。上面介绍日志监听器的时候已经提到。
主要来看一下ConfigFileApplicationListener,该监听器非常核心,主要用来处理项目配置。项目中的 properties 和yml文件都是其内部类所加载。具体来看一下:
首先方法执行入口:
这里写图片描述

首先还是会去读spring.factories 文件,List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();获取的处理类有以下四种:

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=	//一个@FunctionalInterface函数式接口
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,//为springCloud提供的扩展类
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,//支持json环境变量
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor //springBoo2提供的一个包装类,主要将`StandardServletEnvironment`包装成`SystemEnvironmentPropertySourceEnvironmentPostProcessor`对象
  • 1
  • 2
  • 3
  • 4
  • 5

在执行完上述三个监听器流程后,ConfigFileApplicationListener会执行该类本身的逻辑。由其内部类Loader加载项目制定路径下的配置文件:

private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
  • 1

至此,项目的变量配置已全部加载完毕,来一起看一下:
这里写图片描述
这里一共6个配置文件,取值顺序由上到下。也就是说前面的配置变量会覆盖后面同名的配置变量。项目配置变量的时候需要注意这点。

后面五个步骤见第二篇:SpringBoot2 | SpringBoot启动流程源码分析(二)


SpringBoot2 | SpringBoot启动流程源码分析(一)

SpringBoot2 | SpringBoot启动流程源码分析(二)

SpringBoot2 | @SpringBootApplication注解 自动化配置流程源码分析(三)

SpringBoot2 | SpringBoot Environment源码分析(四)

SpringBoot2 | SpringBoot自定义AutoConfiguration | SpringBoot自定义starter(五)

SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六)

SpringBoot2 | 条件注解@ConditionalOnBean原理源码深度解析(七)

SpringBoot2 | Spring AOP 原理源码深度剖析(八)

SpringBoot2 | SpingBoot FilterRegistrationBean 注册组件 | FilterChain 责任链源码分析(九)

SpringBoot2 | BeanDefinition 注册核心类 ImportBeanDefinitionRegistrar (十)

SpringBoot2 | Spring 核心扩展接口 | 核心扩展方法总结(十一)

500元卡时GPU资源,限时免费申领中!

05-14

海量GPU计算资源,预装AI框架和开发环境,开机即用;7*24小时专家团队提供多元服务,让计算科研省时、省力、省心!

Spring Cloud(二)

Valentino112358的博客

 84

Hystrix 容错机制 在不改变各个微服务调用关系的前提下,针对错误情况进行预先处理。 设计原则 1、服务隔离机制 2、服务降级机制 3、熔断机制 4、提供实时的监控和报警功能 5、提供实时的配置修改功能 Hystrix 数据监控需要结合 Spring Boot Actuator 来使用,Actuator 提供了对服务的健康健康、数据统计,可以通过 hystrix.stream 节...

表情包

  • u010391342

    codeing_doc:为何我在springboot2.0.4源码中看到是 public SpringApplication(Class&lt;?&gt;... primarySources) { this(null, primarySources); } 和文章上你出现的不一样啊2 年前回复

    4

    • qq_36751129

      S型烟雾咖啡回复我家宠物叫贝拉:感谢大佬1 年前回复

    • qq_24958783

      我家宠物叫贝拉回复S型烟雾咖啡:他这个版本不是 2.0.4 , 应该是低版本 . 我刚才试了下 SpringBoot 1.5.8 版本。 源码是跟他一样的。1 年前回复

    • qq_36751129

      S型烟雾咖啡回复:同问1 年前回复

  • Winter_chen001WinterChen的博客:
     
    1. //获取监听器,这里是第二次加载spring.factories文件

    2. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

    这里并不会第二次加载spring.factories文件,因为第一次在加载的时候就将这些文件中的类加入到缓存中了,第二次是直接从缓存中获取,一点小小的意见2 年前回复

    3

    • j654436516

      站立小海豹回复linxirong1127:我觉得楼主说得没错,我看的2.3.0版本,最外层缓存key值是classloader,第二层map里面的key值已经有ApplicationContextInitializer.class,这里不需要重新加载,只需要读取缓存即可6 月前回复

    • chengguotao

      NullPointExceptionc回复:你说的没问题,这个些监听是初始化的时候保存在SpringApplication中的,构建EventPublishingListenter,时候通过application.getListeners(),放入广播器中的1 年前回复

    • linxirong1127

      linxirong1127回复:设置系统初始化器时,this.setInitializers方法中,是以ApplicationContextInitializer.class作为key去读取spring.factories文件,构建ApplicationContextInitializer.class对应的实现类properties对象, 所以在设置系统监听器的时候,缓存中是没有的ApplicationListener.class的实现类properties对象的,我觉得作者没写错1 年前回复

  • zzc12121扎哇开发攻城狮:作者大佬,你一开始怎么点进那个
     
    1. public SpringApplication(Object... sources) {

    2. //初始化

    3. initialize(sources);

    4. }

    这部分的,是点进run方法吗还是其他的9 月前回复

    1

  • QQ70945934

    码哥天亮前灬晚安:能说一下源码项目怎么跑起来吗?发现很多个包互相依赖,spring core,spring-bean,spring-boot包。我下载源码后发现各种报错1 年前回复

    1

    • qq_24067089

      萧凡君回复:用idea直接就可以跑10 月前回复

  • qq_26052969

    qq_26052969:话说作者貌似是众安保险的,我看到健康险有个人和你头像名字都一样!3 年前回复

    1

    • qq_26052969

      qq_26052969回复张书康:哈哈,核心系统部的3 年前回复

    • woshilijiuyi

      张书康回复:这么巧。确实是健康险的,你是哪个部门的?3 年前回复

      1

  • Tisfy

    爱码士Tisfy:深得人心,正如古人云:沉舟侧畔千帆过,病树前头万木春。1 月前回复

  • weixin_40724414

    青灰色的墙:请问博主,springboot在启动的时候,配置在application.yml中的信息,在哪些地方用到了5 月前回复

    • woshilijiuyi

      张书康回复:不客气4 月前回复

    • weixin_40724414

      青灰色的墙回复张书康:好的多谢博主4 月前回复

    • woshilijiuyi

      张书康回复:里面的配置信息会被封装到 enviroment 中,在加载配置类时,会从enviroment对象中获取。4 月前回复

  • u010031813码哥半吊子的程序狗:樓主您好:有點沒有看明白,如果你有時間能否再指導一下
     
    1. 这里会根据事件类型ApplicationStartingEvent获取对应的监听器,在容器启动之后执行响应的动作,有如下4种监听器:

    我沒有搞懂的地方是這4個監聽器是怎麼產生的呢6 月前回复

    • woshilijiuyi

      张书康回复:spring的监听器都是在配置文件里指定的,然后全部加载到内存。根据事件类型进行筛选。6 月前回复

  • f45056231p

    f45056231p:转载一下,方便自己慢慢研究2 年前回复

相关推荐

SpringBoot源码深度解析():SpringBoot的自动配置原理...

4-17

SpringBoot流行之前,程序员大多是用SSM框架整合来进行WEB后端开发。这种方式非常麻烦,需要手动引入大量的包,还要配置很多XML文件,光是搭建环境就需要很久。 随着“约定大于配置”理念的流行,SpringBoot随之兴起,它大大简化了web开发的流程,...

SpringBoot2 | Spring AOP 原理深度源码分析_u01451317...

4-11

Spring AOP 多种代理机制相关核心类介绍。 Spring Boot 中AOP注解方式源码分析。 Spring Boot 1.x 版本和 2.x版本 AOP 默认配置的变动。 Spring AOP 多种代理机制相关核心类介绍 先介绍些Spring Aop中些核心类,大致分为三类: ...

SpringBoot源码深度解析springBoot 源码环境构建

qq_34341457的博客

 61

SpringBoot 源码深度解析 第五章 springBoot 源码环境构建 文章目录SpringBoot 源码深度解析前言源码环境搭建 前言 从这章开始,我们来系统的学习下spring Boot的源码,在学习源码之前,先来建立套简单的源码环境 源码环境搭建 下载源码 https://github.com/spring-projects/spring-boot/releases 环境准备 ● JDK1.8+ ● Maven3.5+ 编译源码 ● 进⼊spring-boot源

SpringBoot启动过程原理

RainSun

 4万+

1.1 Springboot启动: @SpringBootApplication public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class,args); } } 从上面代码看,调用了...

spring boot:日志系统源码深度解析_布道

5-1

总所周知,spring boot对各类日志组件进行了集成,使用起来非常便捷,让我们需要定义对应日志框架的配置文件,比如LogBack、Log4j2等,代码内部便可以直接使用。话不多说,接下来让我们来领略spring这块的奥秘吧。目录spring如何集成日志组件Logging...

SpringBoot源码深度解析(五)springBoot 日志管理_茶叶...

5-4

SpringBoot 源码深度解析第四章 springBoot 日志管理文章目录SpringBoot 源码深度解析前言、日志框架介绍前言这章主要介绍springBoot 日志管理、日志框架介绍在项目的开发中,日志是必不可少的个记录事件的组件,不管是记录运行情况...

深入理解Spring 之 源码剖析 SpringBoot Aop 切面编织过程和代理执行过程

ignore

 6313

分析 SpringBoot AOP 原理

Spring Boot启动流程概述-面试

zxing的博客

 2万+

1、创建SpringApplication实例: public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { this.sources = new LinkedHashSet(); this.bannerMode = Mode.CONSOLE; ...

SpringBoot视频教程全家桶

03-01

<p> 本课程通过以Spring Boot 2.x为技术主线,发散式集成覆盖其他相关知识点,并进行逐实战讲解。 </p> <p> 通过本系列课程的学习,你能够学到以下内容: </p> <p> <br /> </p> <ol> <li> 不仅仅能收获到Spring Boot的使用的知识, </li> <li> 更能快速扩充知识面,补全基础知识, </li> <li> 快速Spring Boot入门到实战。 </li> <li> 更多基于Spring Boot的组件集成; </li> <li> Spring相关功能及特性在Spring Boot中的使用; </li> <li> 部分功能核心源码分析等 </li> </ol> <p> 同时,本课程也可作为大家在日常实践中可快速学习、参考的视频集锦。 </p>

springboot源码解析详细版

plumblum的博客

 5183

springboot源码解析 Spring Boot 的入口类 @SpringBootApplication public class StartupApplication { public static void main(String[] args) { SpringApplication.run(StartupApplication.class, args)...

Spring Boot 源码分析

莫凡的博客

 9068

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域rapid application development成为领导者。 Spring boot的特点 创建独立的Spring应用程序 嵌入的T...

SpringBoot启动全流程源码解析超详细版

July的博客

 5509

我们在使用SpringBoot启动项目的时候,可能只需加个注解,然后启动main,整个项目就运行了起来,但事实真的是所见即所得吗,还是SpringBoot在背后默默做了很多?本文会通过源码解析的方式深入理解SpringBoot启动全过程 SpringBoot启动过程流程图 源码解析 大家不要抗拒源码解析,这个非常优秀的代码,我们如果能够学会对自己代码编写水平大有裨益 首先,我们先来看下SpringBoot项目的启动类 @SpringBootApplication public class Sp.

Spring Boot源码深度解析

sinat_41107701的博客

 1290

之前也看过不少spring boot的源码解析,感觉都不是很理想应该是自己太菜,看不懂 哈哈哈。本文旨在对spring boot启动的源码解析分析的很透彻 原文 https://mp.weixin.qq.com/s/HPFfgI7ZKacc0r5EXlmwCA ...

SpringBoot启动流程总结

mnicsm的博客

 3万+

直很好奇SpringBoot这么个大怪物,启动的时候做了哪些事情,然后看了很多老师讲的教学视频,然后自己想好好整理下,做下学习笔记下次也方便自己阅读 1、首先从main方法开始看 public static void main(String[] args) { //代码很简单SpringApplication.run(); SpringApplication.run(Cons...

springboot 源码_springboot源码解析

weixin_39669202的博客

 557

1、springboot是什么?脚手架,纵观框架的发展过程,最终由springboot出来做了SSM的整合,方便程序员偷懒,因为SSM整合过程中有很多的配置,很多的依赖,很容易出错,也不方便快速开发。2、spring创建对象的过程,图解开始springboot源码讲解1、springboot的启动过程1、解释下beanFactory和factoryBean之间的区别?二者都是用来生产对象的,但是f...

Spring Boot 1.5.3 源码深入分析

刘本龙的专栏

 2799

  更多springboot2.X文章请移步至博主专栏:spring boot 2.X/spring cloud Greenwich   目录 1. 项目初始化过程 springboot启动类 SpringFactoriesLoader工厂加载机制 总结初始化initialize过程 run方法: spring事件 自定义spring事件 springboot启动过程中的事件广...

Spring AOP 原理源码深度剖析

方志朋的专栏

 2万+

本文转载于公众号:吉姆餐厅ak 概述 AOP(Aspect-Oriented Programming) 面向切面编程。Spring Aop 在 Spring框架中的地位举足轻重,主要用于实现事务、缓存、安全等功能。本篇主要是对源码进行深度分析。 主要介绍以下三个方面: Spring AOP 多种代理机制相关核心类介绍。 Spring Boot 中AOP注解方式源码分析。 Spring B...

SpringBoot2启动流程深入分析

Al1en的博客

 492

title: SpringBoot2.StartProcess.depth StartProcess提纲 启动监听器 获取环境 创建容器 准备容器 刷新容器 刷新容器后扩展 昨天了咱们把大的过程说了下,今天咱们把细化的过程详细写写。 之后再根据这几个细化过程,继续来遍深入的源码解读。 点关于源码阅读的心得就是先看大架构布局,然后细看各个组成模块。 明白各个模块用到的技术 通过上面的方式...

SpringBoot2 | Spring AOP 原理深度源码分析

程序员阿康

 1万+

概述 AOP(Aspect-Oriented Programming) 面向切面编程。简单来说,就是将影响对象行为的些公共方法抽取出来,做成公共部分即为切面。使用方式就不用阐述了,本系列主要是对源码进行深度分析和总结。 UML图 Spring Aop 自动装配核心类 UML图: 源码 springboot 自动装配肯定还是从spring.factories开始: # Auto Config...

全方位深入解析最新版SpringBoot源码.txt

04-17

第1章 死磕源码,剑指荣耀【用源码武装你的竞争力】 首先点明SB框架的“江湖地位”,学源码三大优势:团队核心、通关面试、自我修炼。接着课程整体全貌,有图有真相。图解源码:看得见的流程;仿写框架:学得会的源码;学完源码:装的了的牛逼。最后为了香车美女,海景别墅,让源码为实力代言~ ... 1-1 实力护航:用SpringBoot源码为实力代言 试看 第2章 全局流程解析图胜千言,探启动加载器之魅力】 本章开篇就直奔主题:动手进行开发环境搭建;然后单刀直入:分别基于SSM和SpringBoot搭建项目工程,通过实践让小伙伴们感受SpringBoot框架优越的快感; 最后图胜千言:让大家窥框架整体启动流程图,在进入正式课程前纵览全貌。 ... 2-1 万事俱备:SpringBoot项目环境准备 2-2 以史为鉴:传统SSM工程搭建演示 2-3 SB的优越感:SpringBoot工程搭建演示 2-4 图胜千言:框架整体启动流程 第3章 初始化器解析【 万事开头难】 本章会对系统初始化器做个全面介绍,让同学们先掌握它的理论知识,再通过动手实践巩固吸收。 最后围绕源码给同学们解析springboot工厂加载机制即框架拓展点实现是如何载入到框架中以及系统初始化器的生效原理。 3-1 览群山:系统初始化器概览 3-2 授人以渔:系统初始化器实战 3-3 打破砂锅:工厂加载机制解析 3-4 庖丁解牛:系统初始化器解析 3-5 英雄所见:系统初始化器总结 第4章 ***解析【眼观六路,耳听八方】 本章先讲解下***设计模式,通过理论分析其必备要素有哪些,再动手写代码来实现这些要素,写完后对比SpringBoot框架内的实现。接着对个框架事件是如何触发指定***做详细解析,最后学以致用动手来实现个自定义***以通关这部分内容。... 4-1 博览群书:***设计模式介绍 4-2 力学笃行:动手实现***设计模式 4-3 枝对叶比:框架内***设计模式实现 4-4 恍然大悟:监听事件触发机制解析上 4-5 醍醐灌顶:监听事件触发机制解析下 4-6 学以致用:自定义***实战 4-7 归根结底:系统***章节总结 4-8 ***应用案例 4-9 ***应用案例二 第5章 bean解析举攻克框架之魂】........

SpringBoot 源码解读

hongtinghua的博客

 2万+

Springboot之前出现的问题 Spring框架需要进行大量的配置 项目的依赖管理冲突 为什么是SpringBoot Spring Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。 ...

互联网架构-SpringBoot源码深度解析-033:SpringBoot源码深入解析

枫火的博客

 56

033:SpringBoot源码深入解析SpringBoot基本实现原理回顾2 SpringApplication构造函数初始化3 WebApplicationType类型的作用4 SpringApplication构造函数原理5 SpringBoot如何设置Banner图7 @EnableAutoConfiguration原理 1 SpringBoot基本实现原理回顾 课程内容: 1.SpringApplication启动流程分析 2.SpringBoot之Tomcat启动流程分析 3.SpringB

SpringBoot启动源码解析

ksemusic的博客

 1851

分析SpringBoot启动源码 分析SpringBoot启动源码 分析SpringBoot启动源码

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页

张书康

码龄10年 暂无认证

54

原创

2万+

周排名

2万+

总排名

35万+

访问

等级

3070

积分

700

粉丝

232

获赞

108

评论

770

收藏

专栏达人

持之以恒

勤写标兵Lv1

私信

关注

热门文章

最新评论

最新文章

2019年14篇

2018年33篇

2017年6篇

2016年1篇

目录

  1. 概述:
  2. 源码分析
  3. 一:获取并启动监听器
  4. 1)获取监听器
  5. 2)启动监听器:
  6. 二:环境构建:

 

分类专栏

举报

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值