spring boot启动过程源码

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

  

一、初始化listeners

 

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

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

 

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

 

 

二、主要的listerners

org.springframework.boot.context.config.ConfigFileApplicationListener

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

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

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

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

 

三、创建context 

org.springframework.boot.SpringApplication.createApplicationContext()

 

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)

以springcloud-config为例: 

读取远程配置完成

注意:通过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()

调用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)

org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(Collection, BeanDefinitionRegistry)

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

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

 

来源:

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);

}时传入的

org.springframework.context.annotation.ConfigurationClassParser.parse(Set)

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

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

 

 

然后通过解析最开始传入的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...)

 

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

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

 

 

定义注册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对象

 findCandidateComponents(String basePackage)

AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);

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

org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(Collection, 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实例

refresh:finishBeanFactoryInitialization(beanFactory);

主要在

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

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

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

 

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

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

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

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])-----------》>org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(String, RootBeanDefinition, Object[])

instantiateUsingFactoryMethod(String, RootBeanDefinition, Object[]) 

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

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

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

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

@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)

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

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 matchingBeans = findAutowireCandidates(beanName, type, descriptor);

addCandidateEntry(Map, String, DependencyDescriptor, Class)

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

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

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

 

 也就是说,当注入的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)

至此,非懒加载且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源码)此处拦截方法调用

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

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

 

 

在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)

2、@bean注解的方法

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

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

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

此处的beanFactory即下面的DefaultListableBeanFactory

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

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

检测到@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)

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

最后通过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

 

你可能感兴趣的:(spring boot启动过程源码)