原因
Spring Framework 提供了除IOC之外的很多有意思的性能,深入研究其技术原理,可在我的项目技术选型上提供更多的思路和技术把控。Spring Framewrok 代码由大佬精心打磨,能够从性能实现上学习和模拟。另外Spring Framework是Java我的项目开发的根底,其余技术框架都会基于或者与Spring 兼容,钻研其中的技术原理,可疾速把握其余技术框架的技术原理,比方 Spring boot \ Spring cloud...
简述
Spring Framework 呈现的背景是,Java 对象之间调用关系简单,为简化对象调用,Spring Framework 基于Dependency Injection,将对象的控制权转移到BeanFactory,由框架负责对象的生命周期,将对象与Bean进行映射,Bean的生命周期由欠缺的管理机制。
本文将会依据本人对Spring Framework的了解编辑。
注释
Spring Framework的核心技术非IOC莫属,BeanFactory接口能够将IOC的性能根本体现进去,子接口与子类实现各自的职责,档次清晰,职责清朗,能够作为面向对象的编程范文。
BeanFactory
正文中解释了Spring 的根本行为,基于Bean Definition创立Bean实例,由Bean Factory负责对象的创立、以及属性的赋值。
- 正文中提到一个说法,依赖 dependency injection 通常来说是比拟好的。凭借 Dependency Injection 以推送的模式去配置利用对象通过setters 或者 constructors,而不是应用任何模式的拉去配置,比方BeanFactory lookup。
- BeanFactory会加载来自多种形式配置的 bean definition, 比方 xml 、配置bean的package ,bean definition 如何存储时无所谓的。激励反对bean之间援用的实现。
- 依赖注入性能是实现BeanFactory接口和子接口。
ListableBeanFactory
BeanFactory接口的扩大,能够列举所有的Bean实例,该接口的实现类要预加载所有单实例Bean.
HierarchicalBeanFactory
容许设置父容器,实用于web环境,Spring 有一个外围BeanFactory 还有一个Web BeanFactory.
ApplicationContext
BeanFactory定义了Spring Framework的根本思维和个性,解决了我的项目开发中外围痛点,另外还有其余的个性减少开发工作中的便利性,比方国际化、事件、资源加载等性能。
继承下列所有接口:
- EnvironmentCapable
- ListableBeanFactory
- HierarchicalBeanFactory
- MessageSource
- ApplicationEventPublisher
- ResourcePatternResolver
ConfigureableApplicationContext
BeanFactory接口的扩大,减少BeanFactory的配置能力,接口中的办法仅在容器启动或者销毁时应用,比方启动时须要的BeanFactoryPostProcessor, ApplicationListener, ResourceLoader ...
以上接口定义Spring Framework 框架的根本行为。
AbstractApplicationContext
ApplicationContext接口的形象实现,已实现次要的Spring Frameword 个性,ApplicationContext接口定义的性能,都能够在此类中提供默认实现。
浏览源码,大抵性能如下:
- 结构器中可设置 resourcePatternResolver 属性,创立PathMatchingResourcePatternResolver 对象。
- 结构器中可设置父容器,并交融父容器中的环境变量。
- 实现 ApplicationContext 中的接口,比方 publishEvent setStartupDate ...
- 实现 ConfigurationApplicationContext 中的接口,比方 addBeanFactoryPostProcessor addApplicationListener refresh() registerShutdownHook close ...
// refresh 办法波及到的办法。
prepareRefresh prepareBeanFactory postProcessBeanFactory registryBeanPostProcessors invokeBeanFactoryPostProcessors initMessageSource initApplicationEventMulticaster initLifecycleProcessor registerListeners finishBeanFactoryInitialization finishRefresh
- 实现 BeanFactory 中的接口,比方 getBean isSingleton isTypeMatch
- 实现 ListableBeanFactory 中的接口,比方 containsBeanDefinition getBeanDefinitionNames findAnnotationOnBean ..
- 实现 HierarchicalBeanFactory 中的接口,比方 getParentBeanFactory getInternalParentBeanFactory ...
- 实现 MessageSource 中的接口,比方 getMessage getMessageSource ...
- 实现 ResourcePatternResolver 中的接口,比方getResources
- 实现 Lifecycle 中的接口,比方start stop isRunning
- 形象办法 refreshBeanFactory ...
GenericApplicationContext
残缺的ApplicationContext实现,实现了BeanDefinitionRegistry接口的办法,领有注册BeanDefinition的能力,能够笼罩一些BeanFactory的属性。
- 结构器中创立 DefaultListableBeanFactory。
- 配置BeanFactory allowBeanDefinitionOverriding bean定义笼罩的问题 allowEagerClassLoading 是否加载标记为懒加载的类。
- 实现 AbstractApplicationContext 中的虚构办法 refreshBeanFactory getBeanFactory ...
- 实现 BeanDefinitionRegistry 接口,比方 registerBeanDefinition isBeanNameInUse
- 手动注册Bean registerBean.
AnnotationConfigApplicationContext
接管 component class 、Configuration annotated class,@Component JSR330 javax.inject annotation.
容许一个接一个应用register办法注册类,扫描class path。Bean annotation 能够被后续的笼罩。
结构器中初始化 AnnotatedBeanDefinitionReader ClassPathBeanDefinitionScanner。或者手动注册一个启动类,并启动容器启动操作 refresh.
DefaultListableBeanFactory
一个很外围的类,能够说是IOC性能的承载者。继承抽象类 AbstractAutowireCapableBeanFactory。
- 实现 BeanFactory 残余的接口实现 getBean getBeanProvider resolveBean ...
- 实现 ListableBeanFactory 接口,比方 getBeanDefinitionNames containsBeanDefinition ...
- 实现 ConfigurableListableBeanFactory 接口,比方 registerResolvableDependency isAutowireCandidate preInstantiateSingletons
- 实现 BeanDefinitionRegistry 接口,比方 registerBeanDefinition registerSingleton
- 解决依赖的一些办法。resolveNamedBean resolveDependency doResolveDependency resolveMultipleBeans
AbstractAutowireCapableBeanFactory
实现默认的Bean创立,具备RootBeanDefinition指定的全副性能。
应用结构器解析提供bean创立,属性填充,wiring,初始化。
反对结构器注入、名字或类型注入。
没有任何的bean注册能力。
通过上述的接口和类的介绍,BeanFactory的子类和相干子接口有个了大抵的理解,应用由上至下的程序介绍了spring Ioc 容器的性能,其中还有一些类或者接口没有介绍到,能够在源码中进入具体理解。
Spring Framework 启动流程。
Spring的启动流程能够简略形容为启动框架的提供性能,加载并初始化开发人员定义的类。
Spring Framework 目前简直所有开发人员都会采纳基于注解的模式开发利用。首先会应用new AnnotationConfigApplicationContext() 启动一个Spring Application Context。
AnnotationConfigApplicationContext 是继承了 GenericApplicationContext 和 AbstractApplicationContext,加载子类时会先加载父类,并应用父类的无参结构或者指定的有参结构创立父类。GenericApplicationContext的无参结构器中会创立一个DefaultListableBeanFactory,对于DefaultListableBeanFactory的父类AbstractAutowireCapableBeanFactory 同样也会被加载到Jvm中,创立对应Class对象。AbstractApplicationContext是一个抽象类,不过其中动态属性和静态方法也会被初始化,创立 PathMatchingResourcePatternResolver 作为默认的 ResourcePatternResolver。
初始化完父类后,就会执行 AnnotationConfigApplicationContext 无参结构器,创立 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefininationScanner。
AnnotatedBeanDefinitionReader的结构器中,除了一些赋值外,会执行 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
这行代码对基于注解的利用尤为的至关重要。其中会将一批框架提供的配置类包装为Bean Definition放入BeanFactory,其中包含:
- ConfigurationClassPostProcessor
- AutowiredAnnotationBeanPostProcessor
- CommonAnnotationBeanPostProcessor
- EventListenerMethodProcessor
- DefaultEventListenerFactory
- AnnotationAwareOrderComparator
- ContextAnnotationAutowireCandidateResolver
大多是一些后置处理器和工具类。
ClassPathBeanDefininationScanner次要是用来扫描classpath门路下类,继承 ClassPathScanningCandidateComponentProvider 提供扫描过程中的一些配置。
以上就是AnnotationConfigApplicationContext对象创立的流程,行将进入 AbstractApplicationContext.refresh()
办法。
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); beanPostProcess.end(); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); contextRefresh.end(); } } }
这是一个Spring context的启动流程,有些context能够启动屡次,有些只能启动一次,另外也会提供勾销启动和重新启动的API.
prepareRefresh()
筹备启动Spring context
- 设置启动工夫
- 激活工作标识
- 初始化context中所有的 placeholder property sources
- 验证启动比方设置的变量
- 保留重新启动前的ApplicationListener
obtainFreshBeanFactory()
告诉子类刷新外部的BeanFactory,其中子类比拟关注 GenericApplicationContext。
- 原子更新刷新标识。
- 设置BeanFactory的惟一标识。
prepareBeanFactory()
筹备上下文中的BeanFactory,配置规范context中的classLoader 和一些 PostProcessors
- 若要应用SPEL,则配置StandardBeanExpressionResolver。
- 减少ResourceEditorRegistrar 到 propertyEditorRegistrar。
- 配置剖析依赖时须要疏忽的接口 EnvironmentAware EmbeddedValueResolverAware ResourceLoaderAware
- 配置 ApplicationContextAwareProcessor ApplicationListenerDetector ApplicationEventPublisherAware MessageSourceAware ApplicationContextAware ApplicationStartupAware,这些接口须要框架提供反对,不须要在依赖注入时解决。
- 若要应用加载时创立代理,则配置LoadTimeWeaverAwareProcessor ContextTypeMatchClassLoader
- 配置解决依赖注入时须要注入的对象,比方Bean须要一个 ApplicationContext,在进行注入时会将配置的对象注入到Bean当中。
- 注册几个环境变量相干的Bean,systemProperties systemEnvironment。
postProcessBeanFactory()
解决 postProcessBeanFactory,暂未发现无效调用,是个空办法。
invokeBeanFactoryPostProcessors()
调用已注册的postProcessBeanFactory。
应用委托模式将PostProcessor的注册工作搁置到 PostProcessorRegistrationDelegate中,调用 invokeBeanFactoryPostProcessors(),解决context中的BeanFactoryPostProcessor。
判断BeanFactory是否继承BeanDefinitionRegistry接口,没有继承就会间接调用 invokeBeanFactoryPostProcessors解决context中的beanFactoryPostProcessors。若继承BeanDefinitionRegistry
- 对context中的beanFactoryPostProcessors,进行分类,属于BeanDefinitionRegistryPostProcessor的 postProcessor 执行 postProcessBeanDefinitionRegistry()。
- 获取BeanFactory中的 BeanDefinitionRegistryPostProcessor.class 类型的BeanName数组,接下来就会遍历BeanName数组。
- 若bean实现了 PriorityOrdered \ Ordered 类,就会调用 invokeBeanDefinitionRegistryPostProcessors 解决BeanDefinition的注册工作。逻辑较多,独立在后续阐明。
- 接着会调用 invokeBeanFactoryPostProcessors 执行 postProcessBeanFactory().
- 对@Configuration的类创立代理,并注册 ImportAwareBeanPostProcessor 到 BeanPostProcessor 的 BeanPostProcessor.
- 对BeanFactoryPostProcessors进行分类和排序 invokeBeanFactoryPostProcessors.
registerBeanPostProcessors()
注册BeanPostProcessors 去拦挡Bean的创立。
- PostProcessorRegistrationDelegate.registerBeanPostProcessors();
- 将BeanFactory中的 BeanPostProcessor BeanDefinition 转换为 BeanFactory的 BeanPostProcessor.
initMessageSource()
初始化context中的国际化。
initApplicationEventMulticaster()
初始化context中的事件机制。
onRefresh()
初始化在特定的子context中的特定Bean。
registerListeners()
查看context中的所有Listener,并注册他们。
finishBeanFactoryInitialization()
实例化所有非懒加载的单实例Bean。
finishRefresh()
公布事件。
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()
- 查看是否已执行过,不能反复执行。
- 进入 processConfigBeanDefinitions()。
获取Context中被@Configuration标注的类。
- 判断BeanDefinition是否领有属性 ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE,作为已解决的标识。
借助工具类判断 ConfigurationClassUtils.checkConfigurationClassCandidate()
- BeanDefinition中有BeanClassName属性的,没有FactoryMethodName的。
- 获取BeanDefinition中的AnnotationMetadata,可通过AnnotationMetadata.introspect(beanClass) metadataReaderFactory.getMetadataReader(className) 获取。
- AnnotationMetadata 中有设置 @Configuration注解的并且注解的属性 proxyBeanMethods为TRUE的。能够作为 full configuration 进行后续的 parse解决。
- 那些有 AnnotationMetadata 或者有 Component ComponentScan Import ImportResource 的注解 或者 有类中有办法应用@Bean BeanDefinition 就是一个 lite configuration 类。可会进行后续的 parse解决。
- 若AnnotationMetadata中有Order注解,会设置到BeanDefinition中。
- 将符合条件的BeanDefinition收集起来。
- 对获取到的BeanDefinition进行排序。
- 获取并反对定制 componentScanBeanNameGenerator importBeanNameGenerator
- 查看并设置 StandardEnvironment
开始 parse @Configuration标识的类(BeanDefinition)
- 创立 ConfigurationClassParser 对象。
- 进入 processConfigurationClass() 开始进行解析工作。
- 进入 ConditionEvaluator.shouldSkip(),会对@Condition注解进行解析判断是否须要解析此Bean。
- 应用反射技术依据 className 转化为 SourceClass.
- 递归调用 doProcessConfiguration(SourceClass)。
processMemberClasses() 解决标有 @Component 注解的外部类。
- 解析外部类是否有被@Configuration的,会间接调用 processConfigurationClass 进行解析。
processPropertySource() 解决标有 @PropertySource 注解的类。
- AnnotationConfigUtils.attributesForRepeatable() 解析出类上的@PropertySource数组,一一解决。
- 以后 environment 必须是 ConfigurableEnvironment 的子类。
- 获取注解中的 name \ encoding \ value \ ignoreResourceNotFound \ factory。
- 将加载到的信息放到以后环境当中。
ComponentScanAnnotationParser.parse() 解决标有 @ComponentScan 注解的类。
- 创立 ClassPathBeanDefinitionScanner 对象。
- 设置 BeanNameGenerator \ ScopedProxyMode \ ScopeMetadataResolver \ ResourcePattern \ IncludeFilter \ ExcludeFilter \ BeanDefinitionDefaults .
- 解析注解中的 basePackages \ basePackageClasses .
- 进入 doScan().
- 加载每个 package,将获取到的 metadataReader 作为创立 ScannedGenericBeanDefinition 的参数。
- 判断 ScannedGenericBeanDefinition 是否有被@Component注解,合乎的放入办法后果集中。
- 遍历后果集。
- 判断是否实现 AbstractBeanDefinition,调用postProcessBeanDefinition进行解决。
- 判断是否实现 AnnotatedBeanDefinition,调用AnnotationConfigUtils.processCommonDefinitionAnnotations()进行解决。
- 依据BeanDefinition的抵触处理结果注册BeanDefinition.
- 从加载到BeanDefinition中过滤是否有@Configuration标注的类,有的话间接调用parse().
processImports() 解决标有 @Import 注解的类。
- 判断是否有循环导入的问题
解决导入的类实现ImportSelector 接口
- 加载被导入的类。
- ParserStrategyUtils.instantiateClass() 将注解解析为 ImportSelector 对象 selector。
- 若 selector 实现了 DeferredImportSelector,间接放入deferredImportSelectorHandler。
- 递归解决导入类上的@Import。
解决导入的类实现ImportBeanDefinitionRegistrar 接口
- 加载被导入的类。
- ParserStrategyUtils.instantiateClass() 将注解解析为 ImportBeanDefinitionRegistrar 对象 registrar。
- 增加到 ImportBeanDefinitionRegistrar 中,在@Configuration注解解析实现后再进行加载。
解决导入的其余类
- 间接应用 processConfigurationClass 解决。
addImportedResource() 解决标有 @ImportResource 注解的类。
- AnnotationConfigUtils.attributesFor() 解析出 AnnotationAttributes importResource 。
- 将解析出的resource 放入 ImportedResource 中。
addBeanMethod() 解决标有 @Bean 注解的办法。
- 获取类中应用@Bean的办法 应用Java反射和ASM获取两遍,并进行比拟办法数量和办法名字的比拟。
- 比拟通过的办法放入后果集中。
- 将后果集一一放入BeanMethod
processInterfaces() 解决接口的默认办法。
- 解决继承的抽象类非形象办法或者接口的默认办法
- 将父类或者实现的接口中的@Bean标注的办法放入 BeanMethod
- 循环解决父类或者父接口.
解析 superclass.
- 解决父类,间接返回循环解决.
this.deferredImportSelectorHandler.process() 开始解决提早导入队列.
- 将队列中的ImportSelector一一放入 DeferredImportSelectorGroupingHandler.registry()
- 实现逻辑较简单,后续会持续剖析.
ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()
registerBeanDefinitionForImportedConfigurationClass
- new AnnotatedGenericBeanDefinition(metadata) 构建 BeanDefinition 对象.
- 获取 BeanDefinition 中的 scopeMetadata, 经 scopeMetadataResolver.resolveScopeMetadata()解决 设置BeanDefinition的scope
- importBeanNameGenerator.generateBeanName() 生成BeanName.
- AnnotationConfigUtils.processCommonDefinitionAnnotations()
- 注册BeanDefinition.
- loadBeanDefinitionsForBeanMethod
- loadBeanDefinitionsFromImportedResources
- loadBeanDefinitionsFromRegistrars
- 比照parse前后的registry中的BeanDefinition数量,将未解决的BeanDefiniton持续解决.
- Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes