博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot的启动类是如何将自己交给spring管理的?
阅读量:3922 次
发布时间:2019-05-23

本文共 5285 字,大约阅读时间需要 17 分钟。

SpringBoot的启动类是如何将自己交给spring管理的

一、发现问题:

在学习SpringBoot的自动装配的时候发现问题,启动Application.java类的run()方法时,Application类本身是如何交给spring管理的?

@SpringBootApplicationpublic class Application {
public static void main(String[] args) {
SpringApplication.run(StadiumGatewayApplication.class, args); }}

二、猜测

1、跟@SpringBootApplication有关?

2、是run方法的内部逻辑

三、分析实践

1、首先分析是否是跟@SpringBootApplication有关,查看注解

@SpringBootApplication@Target(ElementType.TYPE)//修饰自定义注解,指定该自定义注解的注解位置,类还是方法,或者属性@Retention(RetentionPolicy.RUNTIME)//被它所注解的注解保留多久,注解的生命周期。可选的参数值在枚举类型 RetentionPolicy 中,一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。@Documented//将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see(后面可以跟类路径等参数实现链接跳转  Ctrl跳转),@param(注释参数) 等。@Inherited//修饰自定义注解,该自定义注解注解的类,被继承时,子类也会拥有该自定义注解@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {

没有找到将本身注入spring容器里的代码。

2、分析是否与run()方法有关

public static ConfigurableApplicationContext run(Class
primarySource, String... args) {
return run(new Class[]{
primarySource}, args);}
public static ConfigurableApplicationContext run(Class
[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);}

再次点进run()方法后就是真正的逻辑,根据方法名猜测方法的作用,是看源码的一个小技巧。

找到了prepareContext()方法。

public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection
exceptionReporters = new ArrayList(); this.configureHeadlessProperty(); SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(); Collection exceptionReporters; try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); Banner printedBanner = this.printBanner(environment); context = this.createApplicationContext(); exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{
ConfigurableApplicationContext.class}, context); //根据方法名判断这是在启动容器前做的事,大概就是这里面了 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); this.refreshContext(context); this.afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } listeners.started(context); this.callRunners(context, applicationArguments); } catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try {
listeners.running(context); return context; } catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); }}
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment); this.postProcessApplicationContext(context); this.applyInitializers(context); listeners.contextPrepared(context); if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null); this.logStartupProfileInfo(context); } ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } Set sources = this.getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); this.load(context, sources.toArray(new Object[0])); listeners.contextLoaded(context);}

再进入load()方法,一直往底下找!

private int load(Class
source) {
if (this.isGroovyPresent() && BeanDefinitionLoader.GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
BeanDefinitionLoader.GroovyBeanDefinitionSource loader = (BeanDefinitionLoader.GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, BeanDefinitionLoader.GroovyBeanDefinitionSource.class); this.load(loader); } if (this.isComponent(source)) {
this.annotatedReader.register(new Class[]{
source}); return 1; } else {
return 0; } }

连蒙靠猜就找到了启动类交给spring管理的地方了!

转载地址:http://pikgn.baihongyu.com/

你可能感兴趣的文章
linux下open()与fopen()
查看>>
小型软件公司的绩效考核
查看>>
程序编译中如何调试configure
查看>>
关于安装multiget出现XML::Parser perl module is required for intltool错误问题的解决
查看>>
从学习export命令理解到的Shell环境和变量生存期
查看>>
《程序员》杂志:小公司如何建设技术中层
查看>>
glibc是什么,以及与gcc的关系?
查看>>
转 arm-linux-gcc和arm-elf-gcc 区别
查看>>
使用 typedef 抑制劣质代码
查看>>
Bluez下的rfcomm层通信测试程序
查看>>
GCC参数详解
查看>>
软件开发者面试百问
查看>>
硬盘安装Fedora 9
查看>>
嵌入式Linux系统的GDB远程调试实践
查看>>
Linux下基于bluez与obex的服务端实现流程
查看>>
Linux命令行程序设计
查看>>
简单实用的线程管理类
查看>>
static的作用
查看>>
蓝牙核心规范中HCI层的研究与开发分析□ 张 熠 姜玉泉 《电脑知识与技术》 2007年第09期
查看>>
蓝牙协议的命令和事件
查看>>