spring boot启动过程源码

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

主要步骤:初始化listeners、环境信息初始化、创建和初始化context

20191017100289\_1.png

20191017100289\_2.png

一、初始化listeners

20191017100289\_3.png

    F:\mvnRespo\org\springframework\boot\spring-boot\1.5.2.RELEASE\spring-boot-1.5.2.RELEASE.ja#/META-INF/spring.factories

20191017100289\_4.png

    F:\mvnRespo\org\springframework\boot\spring-boot-autoconfigure\1.5.2.RELEASE\spring-boot-autoconfigure-1.5.2.RELEASE.jar#/META-INF/spring.factories

20191017100289\_5.png

    org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(ConfigurableEnvironment)

20191017100289\_6.png

20191017100289\_7.png

二、主要的listerners

    org.springframework.boot.context.config.ConfigFileApplicationListener

    org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent)

20191017100289\_8.png

同时,此处会调用loader读取本地配置文件:

20191017100289\_9.png

    org.springframework.boot.context.config.ConfigFileApplicationListener.Loader.Loader(ConfigFileApplicationListener, ConfigurableEnvironment, ResourceLoader)

20191017100289\_10.png

最终通过配置的PropertySourcesLoader.load()获取本地配置文件中的配置

三、创建context

    org.springframework.boot.SpringApplication.createApplicationContext()

20191017100289\_11.png

1、构造方法

    org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext.AnnotationConfigEmbeddedWebApplicationContext()

2、创建各种预定义的PostProcessor和DefaultListableBeanFactory

    ConfigurationClassPostProcessor:@Configuration

    AutowiredAnnotationBeanPostProcessor:@Autowired、@Value、@Inject、@Lookup

    RequiredAnnotationBeanPostProcessor:@Required

    CommonAnnotationBeanPostProcessor:@PostConstruct、@PreDestroy、@Resource、@WebServiceRef、@EJB

    PersistenceAnnotationBeanPostProcessor:@PersistenceContext、@PersistenceUnit

    EventListenerMethodProcessor:@EventListener

    DefaultEventListenerFactory:@EventListener

    AnnotationAwareOrderComparator:@Order

    ContextAnnotationAutowireCandidateResolver:@Lazy、@Qualifier、@Value

3、初始化

    org.springframework.boot.SpringApplication.prepareContext(ConfigurableApplicationContext, ConfigurableEnvironment, SpringApplicationRunListeners, ApplicationArguments, Banner)

20191017100289\_12.png

以springcloud-config为例:

20191017100289\_13.png

读取远程配置完成

注意:通过springcloud-config获取配置时,不会通过org.springframework.boot.env.PropertiesPropertySourceLoader解析。

org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(Environment)获取远程仓库中的配置(具体看springcloud-config源码)

3、最重要部分

    org.springframework.boot.SpringApplication.refreshContext(ConfigurableApplicationContext)

    org.springframework.boot.SpringApplication.refresh(ApplicationContext)

    org.springframework.context.support.AbstractApplicationContext.refresh()

20191017100289\_14.png

调用PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors通过该方法实现调用各个PostProcessor实现对beans的定义(bean的元信息,非初始化,没有生成实例):

主要在ConfigurationClassPostProcessor调用

    org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)

    org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistry)

    org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>)

    org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor>, BeanDefinitionRegistry)

    org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)

    org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistry)

20191017100289\_15.png

来源:

    org.springframework.boot.SpringApplication.prepareContext(ConfigurableApplicationContext, ConfigurableEnvironment, SpringApplicationRunListeners, ApplicationArguments, Banner)

    org.springframework.boot.SpringApplication.load(ApplicationContext, Object[])

    org.springframework.boot.BeanDefinitionLoader.load()

    org.springframework.boot.BeanDefinitionLoader.load(Object)

sources为刚开始public static void main(String[] args) {

new SpringApplicationBuilder(Application.class).web(true).run(args);

}时传入的

20191017100289\_16.png

    org.springframework.context.annotation.ConfigurationClassParser.parse(Set<BeanDefinitionHolder>)

    org.springframework.context.annotation.ConfigurationClassParser.parse(AnnotationMetadata, String)

    org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClass)

20191017100289\_17.png

20191017100289\_18.png

然后通过解析最开始传入的sources(启动类类名),通过

org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClass, SourceClass)解析出@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean注解的类获取注册更多的beanName

如@ComponentScan

1、org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClass, SourceClass)—》

2、org.springframework.context.annotation.ComponentScanAnnotationParser.parse(AnnotationAttributes, String)—————–》3、org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(String…)

20191017100289\_19.png

    Set<BeanDefinitionHolder> scannedBeanDefinitions =this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

20191017100289\_20.png

    scanner.doScan(StringUtils.toStringArray(basePackages));

20191017100289\_21.png

20191017100289\_22.png

定义注册Bean:

@了scope的类

AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);将定义封装成一个ScopedProxyFactoryBean对象的声明(scoped proxy definition),并注册实际targetbean的声明并通过registerBeanDefinition(definitionHolder, this.registry);注册到上下文的工厂对象中

org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(String, BeanDefinition)

在getBean的时候并不会马上实例化targetbean,而是生成一个ScopedProxyFactoryBean对象

20191017100289\_23.png

findCandidateComponents(String basePackage)

20191017100289\_24.png

AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);

配置扫描到的配置类上属性注解:@Lazy、@Primary、@DependsOn、@Role、@Description到配置类上

org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor>, BeanDefinitionRegistry)会被多次调用去处理不同类型的PostProcessor

refresh:registerBeanPostProcessors(beanFactory)

org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)

refresh:onRefresn()

org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh()—->org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer()

默认创建tomcat实例

20191017100289\_25.png

refresh:finishBeanFactoryInitialization(beanFactory);

主要在

org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons()

非懒加载的bean都在此时完成实例化

(注:在@configuration配置类中,如果有@bean注解的方法,则改配置类作为@BEan对应方法的工厂)

20191017100289\_26.png

// 获取FactoryBean实例,FactoryBean的定义beanName前面会加一个&符号

先看非懒加载的单例bean的实例化

方法中最重要的逻辑在org.springframework.beans.factory.support.AbstractBeanFactory.getBean(String)—-》org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String, Class, Object[], boolean)—–》

20191017100289\_27.pngorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])———–》>org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(String, RootBeanDefinition, Object[])

20191017100289\_28.png

instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[])

20191017100289\_29.png

这段代码之后就是解析在factory的类中获取某个bean实例的方法,通过反射执行该方法,以方法名作为beanName

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(String, RootBeanDefinition)

20191017100289\_30.png

实例化完成后回到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])

20191017100289\_31.png

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(String, RootBeanDefinition, BeanWrapper)属性注入

20191017100289\_32.png

20191017100289\_33.png

@Scope注解的bean,在其他类中@autowired的时候,注入的是从之前的beanName生成的对应的ScopeProxyFactoryBean中getObject()出来的代理,并不是真正初始化的bean,只有单例非懒加载的bean才是注入实例化的bean。

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)调用PostProcessor完成注入

org.springframework.beans.factory.annotation.InjectionMetadata.inject(Object, String, PropertyValues)

20191017100289\_34.png

分成员注入和方法注入两种方式,以成员注入为例:

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement.inject(Object, String, PropertyValues)
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DependencyDescriptor, String, Set, TypeConverter)
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DependencyDescriptor, String, Set, TypeConverter)

1、获取需要注入的bean

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

20191017100289\_35.png

    addCandidateEntry(Map<String, Object>, String, DependencyDescriptor, Class<?>)

    org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(String, Class<?>, BeanFactory)

    org.springframework.beans.factory.support.AbstractBeanFactory.getBean(String, Class<T>)

    org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(Object, String, String, RootBeanDefinition)

20191017100289\_36.png

也就是说,当注入的bean的scope属性不为singlon的时候,是从之前实例化的beanName对应的ScopeProxyFactoryBean获取的Proxy对象,真正的bean此时还没有完成实例化

Aware初始化:

RootBeanDefinition)org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(String, Object)完成实现了Aware接口的重写方法(@overwrite)的反射执行

主要调用

org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(Object, String)

20191017100289\_37.png

20191017100289\_38.png

至此,非懒加载且scope为单例的bean完成实例化初始化

finishRefresh()
org.springframework.context.support.AbstractApplicationContext.finishRefresh()
发布上下文更新事件
publishEvent(new ContextRefreshedEvent(this));

以@RefreshScope为例:此时完成bean的实例化初始化(Bean的scope属性跟当前RefreshScope实例的scope属性值相等的)

org.springframework.cloud.context.scope.refresh.RefreshScope.start(ContextRefreshedEven

此时spring的启动完成,但是懒加载的bean还没加载

懒加载第一次调用实例化

org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy)(这个类怎么进来?应该要看spring AOP源码)此处拦截方法调用

20191017100289\_39.png

org.springframework.aop.target.SimpleBeanTargetSource.getTarget()
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(String)

剩下的流程就跟上面的流程差不多了,由于getBean()方法里不会有判断Lazy的地方,所有执行的都会生成实例并初始化

20191017100289\_40.png

在springcloud config执行了refresh之后,不管scope属性是不是scope,不管是不是懒加载,都在第一次调用方法时被org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercep拦截后才重新生成实例

beanName取值方式

1、@configuration,@compenent,@sprintApplication等注解的类

org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(BeanDefinition, BeanDefinitionRegistry)

20191017100289\_41.png

2、@bean注解的方法

org.springframework.context.annotation.ConfigurationClassEnhancer.BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy)

20191017100289\_42.png

关于应用中有同名的实例时,spring的默认策略是后者覆盖前者

org.springframework.context.annotation.ConfigurationClassEnhancer.BeanMethodInterceptor.intercept(Object, Method, Object[], MethodProxy)后半部分

20191017100289\_43.png

此处的beanFactory即下面的DefaultListableBeanFactory

或者org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(String, BeanDefinition)

20191017100289\_44.png

关于@ComponentScan和spring.factories的定义先后顺序,以及条件注解判断时机

20191017100289\_45.png

检测到@EnableAutoConfiguration注解后调用EnableAutoConfigurationImportSelector,此时的调用和上面@CompentScan的执行不在同一个方法栈,由于EnableAutoConfigurationImportSelector继承AutoConfigurationImportSelector且实现order接口org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getOrder()(值为Ordered.LOWEST_PRECEDENCE – 1),因此,在@CompentScan扫描完其他的注解后,才开始通过ImportSelector读取spring.factories文件,结果是直接扫描的@configuration要比配置在spring.factories里的要先定义(非实例化)。

条件注解:

org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistry)

20191017100289\_46.png

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(Set)
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClass, TrackedConditionEvaluator)

20191017100289\_47.png

最后通过org.springframework.context.annotation.ConditionEvaluator.shouldSkip(AnnotatedTypeMetadata, ConfigurationPhase)完成条件注解的判断逻辑。

因此如果@CompentScan扫描的@configuration上的条件注解的条件是配置在spring.factories的bean,那在定义spring.factories的bean之前,已经完成了对@CompentScan扫描的bean的定义,并且已经完成条件注解的过滤,此时在@CompentScan扫描的@configuration上的条件注解无效。

参考

http://m.blog.csdn.net/u013510838/article/details/75126299

http://www.cnblogs.com/dylan-java/p/7468336.html

http://blog.csdn.net/linuu/article/details/50865358

http://www.cnblogs.com/xrq730/p/6361578.html

http://www.cnblogs.com/xrq730/p/6363055.html


来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring boot启动过程源码

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏