1. 启动方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @SpringBootApplication public class Application { public static void main (String[] args) { SpringApplication.run(Application.class, args); } public static void main (String[] args) { SpringApplication app = new SpringApplication (MySpringConfiguration.class); app.run(args); } public static void main (String[] args) { new SpringApplicationBuilder () .sources(Parent.class) .child(Application.class) .run(args); } }
2. 启动流程概览
3. 启动流程详解 3.1 new Application初始化 3.1.1 initializers初始化器 SPI方式设置初始化器initializers:this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
扩展:自定义初始化器,在spring容器启动前执行,实现ApplicationContextInitializer接口,实现方法,在spring.factories中加入org.springframework.context.ApplicationContextInitializer=初始化器类全路径
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 @FunctionalInterface public interface ApplicationContextInitializer <C extends ConfigurableApplicationContext > { void initialize (C applicationContext) ; }public class MyInitializer implements ApplicationContextInitializer { @Override public void initialize (ConfigurableApplicationContext applicationContext) { System.out.println("自定义初始化器执行..." ); ConfigurableEnvironment environment = applicationContext.getEnvironment(); Map map = new HashMap <>(); map.put("name" ,"jack" ); environment.getPropertySources().addLast(new MapPropertySource ("myInitializer" ,map)); System.out.println("myInitializer execute, and add some property" ); } } org.springframework.context.ApplicationContextInitializer=com.intializer.MyInitializer
初始化器的回调 SpringApplication#run()->prepareContext(..)–>applyInitializers(context)
1 2 3 4 5 6 7 protected void applyInitializers (ConfigurableApplicationContext context) { for (ApplicationContextInitializer initializer : getInitializers()) { Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class); Assert.isInstanceOf(requiredType, context, "Unable to call initializer." ); initializer.initialize(context); } }
3.1.2 listeners监听器
SPI方式设置监听器listeners:this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
扩展:自定义监听器(starting-servlet启动前执行 or started-servlet启动后执行),在spring容器启动前(后)执行,实现ApplicationListener接口,实现方法,在spring.factories中加入org.springframework.context.ApplicationListener=初始化器类全路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class MyStartingListener implements ApplicationListener <ApplicationStartingEvent> { @Override public void onApplicationEvent (ApplicationStartingEvent event) { System.out.println("myStartingListener 容器正在启动..." ); } }public class MyStartedListener implements ApplicationListener <ApplicationStartedEvent> { @Override public void onApplicationEvent (ApplicationStartedEvent event) { System.out.println("myStartedListener 容器启动完成..." ); } } org.springframework.context.ApplicationListener=\ com.jack.springbootmybatis.listener.MyStartingListener,\ com.jack.springbootmybatis.listener.MyStartedListener
3.2 run方法
获取监听器,并启动starting类型的监听器
1 2 SpringApplicationRunListeners listeners = this .getRunListeners(args); listeners.starting(bootstrapContext, this .mainApplicationClass);
准备Environment,和配置中心扩展有关
打印Banner;自定义Banner,有txt和image两种方式,在resources目录下创建一个banner.txt的文件就可以自定义banner效果
确定context类型:context = createApplicationContext()
prepareContext,执行初始化器initializers
refreshContext(context) ->AbstractApplicationContext#refresh():创建tomcat容器;创建bean工厂;实例化bean
(1)this.prepareRefresh();上下文刷新前的准备工作:启动日期,设置context的当前状态,初始化属性和环境
(2)获取beanFantory工厂:obtainFreshFactory
(3)准备beanFactory工厂,配置一些标准的特性,比如上下文类加载器和后置处理器等
(4)postProcessBeanFactory(beanFactory):处理一些web相关的bean以及作用域,比如:request和session等
(5)invokeBeanFactoryPostProcessors(beanFactory):执行BeanFactory的后置处理器,解析@Configuration,生成BeanDefinition
扩展:自定义BeanFactoryPostProcessor:实现BeanFactoryPostProcessor,添加@Component注解
1 2 3 4 5 6 7 8 9 10 11 @Component public class JackBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory (ConfigurableListableBeanFactorybeanFactory) throws BeansException { Arrays.asList(beanFactory.getBeanDefinitionNames()).forEach(beanDefinitionName -> System.out.println(beanDefinitionName)); System.out.println("JackBeanFactoryPostProcessor..." ); } }
(6)registerBeanPostProcessors(beanFactory):向BeanFactory中注册bean的postprocessor,用于后续bean创建的拦截操作,应用场景AOP
扩展:自定义BeanPostProcessor:实现BeanPostProcessor,添加@Component
1 2 3 4 5 6 7 8 9 10 11 @Component public class JackBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { if (beanName.equals("userController" )){ System.out.println("找到了userController: " +bean); } return null ; } }
(7)initMessageSource国际化
(8)initApplicationEventMulticaster:初始化一些广播器,用于发布事件
(9)onRefresh:初始化context子类上下文中的其他特别bean,创建tomcat容器等
(10)finishBeanFactoryInitialization(beanFactory):bean的初始化并加入beanFactory中
1-beanFactory.preInstantiateSingletons()
2-获取到所有BeanDefinition的名称 List beanNames = new ArrayList<>(this.beanDefinitionNames)
3-判断当前的bean是否为factorybean if (isFactoryBean(beanName))
4-来到else部分的getBean(beanName)方法
5-判断是否可以从缓存中获取到bean或者父容器中获取:getSingleton(beanName)以及 getParentBeanFactory()
6-getSingleton(String beanName,Object Factory singleFactory),调用singleFactory#getObject 方法时,会来到其实现类createBean(beanName,mbd,args)
7-AbstractAutowireCapableBeanFactory#doCreateBean()
8-选择无参构造函数创建Bean:
执行runners
扩展:自定义runner,在spring容器启动前执行,实现ApplicationRunner接口,实现方法,添加通过@Component注解
1 2 3 4 5 6 7 8 @Component public class MyApplicationRunner implements ApplicationRunner { @Override public void run (ApplicationArguments args) throws Exception { System.out.println("MyApplicationRunner..." ); } }