本文共 5285 字,大约阅读时间需要 17 分钟。
一、发现问题:
在学习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; CollectionexceptionReporters = 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
再进入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/