以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方法启动监听器;
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实例的主要步骤完成。