SpringApplication 的运行过程分析: run()
来源:互联网 发布:什么手机支持双频网络 编辑:程序博客网 时间:2024/06/05 12:02
1.获取 SpringApplicationRunListener 实例
比如 EventPublishingRunListener
// 内部使用SpringFactoriesLoader 加载所有定义的 SpringApplicationRunListener并构造实例// 可以将 SpringApplicationRunListeners 理解为一组这样的实例的集合SpringApplicationRunListeners listeners = getRunListeners(args);
2.向所有 SpringApplicationRunListener 实例通知事件 ApplicationStartedEvent
listeners.starting();
3. 准备环境 Environment
// 准备 Environment : 创建并配置 Enviroment private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // Create and configure the environment ConfigurableEnvironment environment = getOrCreateEnvironment(); configureEnvironment(environment, applicationArguments.getSourceArgs()); // 向所有 SpringApplicationRunListener 实例通知事件 ApplicationEnvironmentPreparedEvent listeners.environmentPrepared(environment); if (!this.webEnvironment) { environment = new EnvironmentConverter(getClassLoader()) .convertToStandardEnvironmentIfNecessary(environment); } return environment; } private ConfigurableEnvironment getOrCreateEnvironment() { if (this.environment != null) { return this.environment; } if (this.webEnvironment) { // 如果是 Web 环境,创建 StandardServletEnvironment 对象 return new StandardServletEnvironment(); } // 如果是非 Web 环境,创建 StandardEnvironment 对象 return new StandardEnvironment(); } protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) { configurePropertySources(environment, args); configureProfiles(environment, args); }
4. 向所有 SpringApplicationRunListener 实例通知事件 ApplicationEnvironmentPreparedEvent
5. 创建 ApplicationContext
/** * 非web环境应用上下文的实现类 * The class name of application context that will be used by default for non-web * environments. */ public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context." + "annotation.AnnotationConfigApplicationContext"; /** * web环境应用上下文的实现类 * The class name of application context that will be used by default for web * environments. */ public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework." + "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext"; // 初始化过程中已经推断过当前应用是否Web应用环境, //下面根据当前应用是否Web应用环境找到相应的ApplicationContext实现类, //AnnotationConfigEmbeddedWebApplicationContext对应非Web环境 //或者 ConfigurableWebApplicationContext对应Web环境 protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { contextClass = Class.forName(this.webEnvironment ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass", ex); } } // 创建 ApplicationContext 实例 return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass); }
ApplicationContext对象实例化的过程只是做了一个Java对象创建的动作吗 ? 并不是那么简单,以缺省 Web应用的情况来看 :
public AnnotationConfigEmbeddedWebApplicationContext() { //创建一个AnnotatedBeanDefinitionReader,注解Bean类程序方式注册的便捷工具,和 //classpath Bean定义扫描器ClassPathBeanDefinitionScanner互为补充,采用同样的 //注解解决机制,但是只针对显式注册的类 //AnnotatedBeanDefinitionReader()构造方法内部会进一步调用工具类 //AnnotationConfigUtils. registerAnnotationConfigProcessors(registry) //注册 6个BeanPostProcessor Bean定义,这也是容器中最早出现的一组Bean定义: //1. annotation.internalConfigurationAnnotationProcessor //2. annotation.internalAutowiredAnnotationProcessor //3. annotation.internalRequiredAnnotationProcessor //4. annotation.internalCommonAnnotationProcessor //5. event.internalEventListenerProcessor //6. event.internalEventListenerFactory this.reader = new AnnotatedBeanDefinitionReader(this); // Bean definition 扫描器 : // 扫描classpath上的Bean定义并注册到 ApplicationContext 或者 BeanFactory // Q : 什么样的会被认为是候选Bean定义 ? // A : @Component, @Repository,@Service,@Controller等Spring注解定义的类,或者 // Java EE 6's javax.annotation.ManagedBean,JSR-330 javax.inject.Named // 注解定义的类 this.scanner = new ClassPathBeanDefinitionScanner(this); }
6. 准备 ApplicationContext
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { // 关联 ApplicationContext 和 Environment context.setEnvironment(environment); // 1.如果外部指定了 Bean 名称生成器,将其作为单例Bean注册到容器, // 2.如果外部指定了资源加载器,设置 ApplicationContext 的资源加载器和相应的类加载器 postProcessApplicationContext(context); // 执行每个 ApplicationContextInitializer 实例的初始化 initialize(context) applyInitializers(context); // 向所有 SpringApplicationRunListener 实例通知事件 ApplicationEnvironmentPreparedEvent listeners.contextPrepared(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); } // Load the sources Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); // 加载 Bean 定义, 只根据源类型将源设置到具体的 Bean定义加载器,并没有全面执行Bean定义加载. // 这里 sources 指定的类,如果有注解@Component,则会被作为Bean定义添加到容器中,比如当前 // SpringApplication的入口类,因为有注解@SpringBootConfiguration,内含了注解@Component, // 所以它会作为作为一个Bean被注册进容器; load(context, sources.toArray(new Object[sources.size()])); // 1.向所有 SpringApplicationRunListener 实例通知事件 ApplicationPreparedEvent // 2.关联 ApplicationContext 和所有 ApplicationContextAware 的 ApplicationListener listeners.contextLoaded(context); }
7.刷新 ApplicationContext
((AbstractApplicationContext) applicationContext).refresh();
8.执行 ApplicationContext 刷新后任务 : 执行 Runners
....# SpringApplication.run()中的代码片段afterRefresh(context, applicationArguments);..../** * Called after the context has been refreshed. * @param context the application context * @param args the application arguments */ protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { callRunners(context, args); } private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<Object>(); // 找出所有的 ApplicationRunner Bean runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); // 找出所有的 CommandLineRunner Bean runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); // 排序 AnnotationAwareOrderComparator.sort(runners); // 调用所有的 Runner for (Object runner : new LinkedHashSet<Object>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
9.向所有 SpringApplicationRunListener 实例通知事件 ApplicationReadyEvent
// SpringApplicationRunListener 会进一步将此事件通知到 ApplicationContext 中去 // Listeners have been registered to the application context so we should // use it at this point if we can context.publishEvent(event);
阅读全文
0 0
- SpringApplication 的运行过程分析: run()
- SpringApplication 的初始化过程分析 : initialize()
- SpringApplication 的启动过程的两个阶段
- MFC的运行过程分析
- CERTI之RTIG的运行过程分析
- Dalvik虚拟机的运行过程分析
- Dalvik虚拟机的运行过程分析
- Dalvik虚拟机的运行过程分析
- Dalvik虚拟机的运行过程分析
- Dalvik虚拟机的运行过程分析
- Dalvik虚拟机的运行过程分析
- Dalvik虚拟机的运行过程分析
- 分析java程序的运行过程
- Dalvik虚拟机的运行过程分析
- 30 自制操作系统,qemu的运行记录,解释run.bat的执行过程
- Servlet 运行过程分析
- ThreadPoolExecutor运行过程分析
- Spring Boot的SpringApplication类详解
- 数据可视化D3-简单说
- 漫谈 Clustering (5): Hierarchical Clustering
- 关于焦点
- bzoj3450 Tyvj1952 Easy
- python学习(一)
- SpringApplication 的运行过程分析: run()
- vue2.0动态改变index中title
- Node.js使用
- Django模版中for循环的方法
- python+Selenium2自动化之路Day2-pip降级selenium3.0
- Ant Design中模态框中订单金额随商品数量与商品类别动态变化的记录
- 车东西 | 腾讯发布AI IN CAR车载系统 智能车机迎来BAT“三国杀”时代
- 腾讯首次公开完整AI战略:三层架构,八大场景
- 锤子新机坚果Pro2支持人脸解锁 腾讯拟在武汉建无人警局