SOFABoot源码解析之启动原理(2)-源码解析

        以SOFABoot自带的RPC案例sofaboot-sample-with-rpc作为SOFABoot应用(其实也是SpringBoot应用)启动源码分析的案例。

        在此提前说明,源码分析主要分析主流程,以及本人认为比较重要的一些内容,对于其它部分,大家可以基于本文档,自行研读。

        在该案例中,采用WEB环境下使用的Spring应用上下文环境org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext。

        在SofaBootRpcDemoApplication的main方法中,调用SpringApplication的静态方法(S   ofaBootRpcDemoApplication.class, args),启动应用: 

1.  publicstatic ConfigurableApplicationContext run(Object[] sources, String[] args) {
2.       return new SpringApplication(sources).run(args);
3.  }

一、  创建SpringApplication实例

        在run方法中,首先创建SpringApplication实例: 

1.  publicSpringApplication(Object... sources) {
2.       initialize(sources);
3.  }

        在SpringApplication构造函数中,调用initialize方法进行SpringApplication实例初始化工作: 

1.  privatevoid initialize(Object[] sources) {
2.       if(sources != null && sources.length > 0) {
3.           this.sources.addAll(Arrays.asList(sources));
4.       }
5.       this.webEnvironment= deduceWebEnvironment();
6.       setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
8.       setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
9.       this.mainApplicationClass= deduceMainApplicationClass();
10. }

        在SpringApplication实例初始化的时候,主要做以下几件事情:

        1.   根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型;

        2.   使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer;

        3.   使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener;

        4.   推断并设置main方法的定义类;

二、  启动SOFABoot应用

        SpringApplication实例初始化完成后,开始执行run方法,启动SOFABoot应用。 

1.  public ConfigurableApplicationContextrun(String... args) {
2.       StopWatchstopWatch = new StopWatch();
3.       stopWatch.start();
4.       ConfigurableApplicationContextcontext = null;
5.       FailureAnalyzersanalyzers = null;
6.       configureHeadlessProperty();
7.       SpringApplicationRunListenerslisteners = getRunListeners(args);
8.       listeners.started();
9.       try{
10.          ApplicationArgumentsapplicationArguments = new DefaultApplicationArguments(args);
12.          ConfigurableEnvironmentenvironment = prepareEnvironment(listeners,
13.                  applicationArguments);
14.          BannerprintedBanner = printBanner(environment);
15.          context = createApplicationContext();
16.          analyzers= new FailureAnalyzers(context);
17.          prepareContext(context, environment,listeners, applicationArguments,
18.                  printedBanner);
19.          refreshContext(context);
20.          afterRefresh(context,applicationArguments);
21.          listeners.finished(context,null);
22.          stopWatch.stop();
23.          if(this.logStartupInfo) {
24.              newStartupInfoLogger(this.mainApplicationClass)
25.                      .logStarted(getApplicationLog(),stopWatch);
26.          }
27.          returncontext;
28.      }
29.      catch(Throwable ex) {
30.          handleRunFailure(context,listeners, analyzers, ex);
31.          throw new IllegalStateException(ex);
32.      }
33. }

        启动SOFABoot应用的主要工作就是创建和刷新Spring应用上下文。此处采用AnnotationConfigEmbeddedWebApplicationContext作为Spring应用上下文的实现类。

        启动SOFABoot应用的主要步骤如下:

        (一)    创建StopWatch实例,并启动,记录任务的运行时间;

        (二)    设置系统属性java.awt.headless;

        (三)    通过SpringFactoriesLoader类loadFactoryNames方法,查找并加载所有spring.factories文件中定义的SpringApplicationRunListener接口的实现,并调用started方法启动监听器;

      (四)   创建Spring应用上下文AnnotationConfigEmbeddedWebApplicationContext:      
1.  protectedConfigurableApplicationContext createApplicationContext() {
2.       Class<?>contextClass = this.applicationContextClass;
3.       if(contextClass == null) {
4.           try{
5.               contextClass =Class.forName(this.webEnvironment
6.                       ?DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
7.           }
8.           catch(ClassNotFoundException ex) {
9.               thrownew IllegalStateException(……);
10.          }
11.      }
12.      return (ConfigurableApplicationContext)BeanUtils.instantiate(contextClass);
13. }

        此处是WEB环境,所以创建AnnotationConfigEmbeddedWebApplicationContext实例: 

1.  publicAnnotationConfigEmbeddedWebApplicationContext() {
2.       this.reader = new AnnotatedBeanDefinitionReader(this);
3.       this.scanner= new ClassPathBeanDefinitionScanner(this);
4.  }

        在AnnotationConfigEmbeddedWebApplicationContext构造函数中,创建AnnotatedBeanDefinitionReader实例,用来处理含有注解的类。创建ClassPathBeanDefinitionScanner实例,用来扫描指定路径下含有注解的类。由于SOFAbBoot主要采用JavaConfig的配置形式,所以此处主要看一下AnnotatedBeanDefinitionReader实例化过程,以了解注解相关处理器的注册过程: 

1.    publicAnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environmentenvironment) {
2.            ……       
3.           AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
4.  }

    在Spring应用上下文中注册所有注解相关的Post Processors: 

1.  public staticSet<BeanDefinitionHolder> registerAnnotationConfigProcessors(
2.           BeanDefinitionRegistryregistry, Object source) {
3.   
4.       DefaultListableBeanFactorybeanFactory = unwrapDefaultListableBeanFactory(registry);
5.       ……   
6.       Set<BeanDefinitionHolder>beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
7.       if(!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)){
8.           RootBeanDefinitiondef = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
9.           def.setSource(source);
10.          beanDefs.add(registerPostProcessor(registry,def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
11.      }
12.  
13.      if(!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
14.          RootBeanDefinitiondef = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
15.          def.setSource(source);
16.          beanDefs.add(registerPostProcessor(registry,def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
17.      }
18.  
19.      if(!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
20.          RootBeanDefinitiondef = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
21.          def.setSource(source);
22.          beanDefs.add(registerPostProcessor(registry,def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
23.      }
24.  
25.      //Check for JSR-250 support, and if present add theCommonAnnotationBeanPostProcessor.
26.      if(jsr250Present &&!registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
27.          RootBeanDefinitiondef = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
28.          def.setSource(source);
29.          beanDefs.add(registerPostProcessor(registry,def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
30.      }
31.      ……   
32.      if(!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
33.          RootBeanDefinition def = newRootBeanDefinition(EventListenerMethodProcessor.class);
34.          def.setSource(source);
35.          beanDefs.add(registerPostProcessor(registry,def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
36.      }
37.      if(!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
38.          RootBeanDefinitiondef = new RootBeanDefinition(DefaultEventListenerFactory.class);
39.          def.setSource(source);
40.          beanDefs.add(registerPostProcessor(registry,def, EVENT_LISTENER_FACTORY_BEAN_NAME));
41.      }
42.  
43.      returnbeanDefs;
44. }

        与注解相关的PostProcessors主要包括ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,EventListenerMethodProcessor,PersistenceAnnotationBeanPostProcessor,DefaultEventListenerFactory。

        其中,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口。当刷新Spring上下文(调用AbstractApplicationContext类refresh方法)过程中,调用AbstractApplicationContext类invokeBeanFactoryPostProcessors方法时,被调用执行。ConfigurationClassPostProcessor解析@Configuration注解,调用ConfigurationClassParser类的parse方法,处理@ComponentScan、@Import、@ImportResource、@Bean注解。

        AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor, RequiredAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor实现了BeanPostProcessor接口,在创建Bean实例时被调用。例如:在刷新Spring上下文(调用AbstractApplicationContext类refresh方法)过程中,调用finishBeanFactoryInitialization方法时,在实例化所有单例Bean对象时被调用。

        EventListenerMethodProcessor,DefaultEventListenerFactory是事件监听器相关的PostProcessors。

        至此,创建AnnotationConfigEmbeddedWebApplicationContext实例的主要步骤完成。

         (五)   准备Spring应用上下文:      
1.  private voidprepareContext(ConfigurableApplicationContext context,
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

任性之闲来无事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值