原因

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负责对象的创立、以及属性的赋值。

  1. 正文中提到一个说法,依赖 dependency injection 通常来说是比拟好的。凭借 Dependency Injection 以推送的模式去配置利用对象通过setters 或者 constructors,而不是应用任何模式的拉去配置,比方BeanFactory lookup。
  2. BeanFactory会加载来自多种形式配置的 bean definition, 比方 xml 、配置bean的package ,bean definition 如何存储时无所谓的。激励反对bean之间援用的实现。
  3. 依赖注入性能是实现BeanFactory接口和子接口。

ListableBeanFactory

BeanFactory接口的扩大,能够列举所有的Bean实例,该接口的实现类要预加载所有单实例Bean.

HierarchicalBeanFactory

容许设置父容器,实用于web环境,Spring 有一个外围BeanFactory 还有一个Web BeanFactory.

ApplicationContext

BeanFactory定义了Spring Framework的根本思维和个性,解决了我的项目开发中外围痛点,另外还有其余的个性减少开发工作中的便利性,比方国际化、事件、资源加载等性能。

继承下列所有接口:

  1. EnvironmentCapable
  2. ListableBeanFactory
  3. HierarchicalBeanFactory
  4. MessageSource
  5. ApplicationEventPublisher
  6. ResourcePatternResolver

ConfigureableApplicationContext

BeanFactory接口的扩大,减少BeanFactory的配置能力,接口中的办法仅在容器启动或者销毁时应用,比方启动时须要的BeanFactoryPostProcessor, ApplicationListener, ResourceLoader ...


以上接口定义Spring Framework 框架的根本行为。

AbstractApplicationContext

ApplicationContext接口的形象实现,已实现次要的Spring Frameword 个性,ApplicationContext接口定义的性能,都能够在此类中提供默认实现。

浏览源码,大抵性能如下:

  1. 结构器中可设置 resourcePatternResolver 属性,创立PathMatchingResourcePatternResolver 对象。
  2. 结构器中可设置父容器,并交融父容器中的环境变量。
  3. 实现 ApplicationContext 中的接口,比方 publishEvent setStartupDate ...
  4. 实现 ConfigurationApplicationContext 中的接口,比方 addBeanFactoryPostProcessor addApplicationListener refresh() registerShutdownHook close ...

// refresh 办法波及到的办法。
prepareRefresh prepareBeanFactory postProcessBeanFactory registryBeanPostProcessors invokeBeanFactoryPostProcessors initMessageSource initApplicationEventMulticaster initLifecycleProcessor registerListeners finishBeanFactoryInitialization finishRefresh

  1. 实现 BeanFactory 中的接口,比方 getBean isSingleton isTypeMatch
  2. 实现 ListableBeanFactory 中的接口,比方 containsBeanDefinition getBeanDefinitionNames findAnnotationOnBean ..
  3. 实现 HierarchicalBeanFactory 中的接口,比方 getParentBeanFactory getInternalParentBeanFactory ...
  4. 实现 MessageSource 中的接口,比方 getMessage getMessageSource ...
  5. 实现 ResourcePatternResolver 中的接口,比方getResources
  6. 实现 Lifecycle 中的接口,比方start stop isRunning
  7. 形象办法 refreshBeanFactory ...

GenericApplicationContext

残缺的ApplicationContext实现,实现了BeanDefinitionRegistry接口的办法,领有注册BeanDefinition的能力,能够笼罩一些BeanFactory的属性。

  1. 结构器中创立 DefaultListableBeanFactory。
  2. 配置BeanFactory allowBeanDefinitionOverriding bean定义笼罩的问题 allowEagerClassLoading 是否加载标记为懒加载的类。
  3. 实现 AbstractApplicationContext 中的虚构办法 refreshBeanFactory getBeanFactory ...
  4. 实现 BeanDefinitionRegistry 接口,比方 registerBeanDefinition isBeanNameInUse
  5. 手动注册Bean registerBean.

AnnotationConfigApplicationContext

接管 component class 、Configuration annotated class,@Component JSR330 javax.inject annotation.
容许一个接一个应用register办法注册类,扫描class path。Bean annotation 能够被后续的笼罩。

结构器中初始化 AnnotatedBeanDefinitionReader ClassPathBeanDefinitionScanner。或者手动注册一个启动类,并启动容器启动操作 refresh.

DefaultListableBeanFactory

一个很外围的类,能够说是IOC性能的承载者。继承抽象类 AbstractAutowireCapableBeanFactory。

  1. 实现 BeanFactory 残余的接口实现 getBean getBeanProvider resolveBean ...
  2. 实现 ListableBeanFactory 接口,比方 getBeanDefinitionNames containsBeanDefinition ...
  3. 实现 ConfigurableListableBeanFactory 接口,比方 registerResolvableDependency isAutowireCandidate preInstantiateSingletons
  4. 实现 BeanDefinitionRegistry 接口,比方 registerBeanDefinition registerSingleton
  5. 解决依赖的一些办法。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

  1. 设置启动工夫
  2. 激活工作标识
  3. 初始化context中所有的 placeholder property sources
  4. 验证启动比方设置的变量
  5. 保留重新启动前的ApplicationListener

obtainFreshBeanFactory()

告诉子类刷新外部的BeanFactory,其中子类比拟关注 GenericApplicationContext。

  1. 原子更新刷新标识。
  2. 设置BeanFactory的惟一标识。

prepareBeanFactory()

筹备上下文中的BeanFactory,配置规范context中的classLoader 和一些 PostProcessors

  1. 若要应用SPEL,则配置StandardBeanExpressionResolver。
  2. 减少ResourceEditorRegistrar 到 propertyEditorRegistrar。
  3. 配置剖析依赖时须要疏忽的接口 EnvironmentAware EmbeddedValueResolverAware ResourceLoaderAware
  4. 配置 ApplicationContextAwareProcessor ApplicationListenerDetector ApplicationEventPublisherAware MessageSourceAware ApplicationContextAware ApplicationStartupAware,这些接口须要框架提供反对,不须要在依赖注入时解决。
  5. 若要应用加载时创立代理,则配置LoadTimeWeaverAwareProcessor ContextTypeMatchClassLoader
  6. 配置解决依赖注入时须要注入的对象,比方Bean须要一个 ApplicationContext,在进行注入时会将配置的对象注入到Bean当中。
  7. 注册几个环境变量相干的Bean,systemProperties systemEnvironment。

postProcessBeanFactory()

解决 postProcessBeanFactory,暂未发现无效调用,是个空办法。

invokeBeanFactoryPostProcessors()

调用已注册的postProcessBeanFactory。

应用委托模式将PostProcessor的注册工作搁置到 PostProcessorRegistrationDelegate中,调用 invokeBeanFactoryPostProcessors(),解决context中的BeanFactoryPostProcessor。
判断BeanFactory是否继承BeanDefinitionRegistry接口,没有继承就会间接调用 invokeBeanFactoryPostProcessors解决context中的beanFactoryPostProcessors。若继承BeanDefinitionRegistry

  1. 对context中的beanFactoryPostProcessors,进行分类,属于BeanDefinitionRegistryPostProcessor的 postProcessor 执行 postProcessBeanDefinitionRegistry()。
  2. 获取BeanFactory中的 BeanDefinitionRegistryPostProcessor.class 类型的BeanName数组,接下来就会遍历BeanName数组。
  3. 若bean实现了 PriorityOrdered \ Ordered 类,就会调用 invokeBeanDefinitionRegistryPostProcessors 解决BeanDefinition的注册工作。逻辑较多,独立在后续阐明。
  4. 接着会调用 invokeBeanFactoryPostProcessors 执行 postProcessBeanFactory().
  5. 对@Configuration的类创立代理,并注册 ImportAwareBeanPostProcessor 到 BeanPostProcessor 的 BeanPostProcessor.
  6. 对BeanFactoryPostProcessors进行分类和排序 invokeBeanFactoryPostProcessors.

registerBeanPostProcessors()

注册BeanPostProcessors 去拦挡Bean的创立。

  1. PostProcessorRegistrationDelegate.registerBeanPostProcessors();
  2. 将BeanFactory中的 BeanPostProcessor BeanDefinition 转换为 BeanFactory的 BeanPostProcessor.

initMessageSource()

初始化context中的国际化。

initApplicationEventMulticaster()

初始化context中的事件机制。

onRefresh()

初始化在特定的子context中的特定Bean。

registerListeners()

查看context中的所有Listener,并注册他们。

finishBeanFactoryInitialization()

实例化所有非懒加载的单实例Bean。

finishRefresh()

公布事件。

ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()

  1. 查看是否已执行过,不能反复执行。
  2. 进入 processConfigBeanDefinitions()。
  3. 获取Context中被@Configuration标注的类。

    1. 判断BeanDefinition是否领有属性 ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE,作为已解决的标识。
    2. 借助工具类判断 ConfigurationClassUtils.checkConfigurationClassCandidate()

      1. BeanDefinition中有BeanClassName属性的,没有FactoryMethodName的。
      2. 获取BeanDefinition中的AnnotationMetadata,可通过AnnotationMetadata.introspect(beanClass) metadataReaderFactory.getMetadataReader(className) 获取。
      3. AnnotationMetadata 中有设置 @Configuration注解的并且注解的属性 proxyBeanMethods为TRUE的。能够作为 full configuration 进行后续的 parse解决。
      4. 那些有 AnnotationMetadata 或者有 Component ComponentScan Import ImportResource 的注解 或者 有类中有办法应用@Bean BeanDefinition 就是一个 lite configuration 类。可会进行后续的 parse解决。
      5. 若AnnotationMetadata中有Order注解,会设置到BeanDefinition中。
      1. 将符合条件的BeanDefinition收集起来。
  4. 对获取到的BeanDefinition进行排序。
  5. 获取并反对定制 componentScanBeanNameGenerator importBeanNameGenerator
  6. 查看并设置 StandardEnvironment
  7. 开始 parse @Configuration标识的类(BeanDefinition)

    1. 创立 ConfigurationClassParser 对象。
    2. 进入 processConfigurationClass() 开始进行解析工作。
    3. 进入 ConditionEvaluator.shouldSkip(),会对@Condition注解进行解析判断是否须要解析此Bean。
    4. 应用反射技术依据 className 转化为 SourceClass.
    5. 递归调用 doProcessConfiguration(SourceClass)。
    6. processMemberClasses() 解决标有 @Component 注解的外部类。

      1. 解析外部类是否有被@Configuration的,会间接调用 processConfigurationClass 进行解析。
    7. processPropertySource() 解决标有 @PropertySource 注解的类。

      1. AnnotationConfigUtils.attributesForRepeatable() 解析出类上的@PropertySource数组,一一解决。
      2. 以后 environment 必须是 ConfigurableEnvironment 的子类。
      3. 获取注解中的 name \ encoding \ value \ ignoreResourceNotFound \ factory。
      4. 将加载到的信息放到以后环境当中。
    8. ComponentScanAnnotationParser.parse() 解决标有 @ComponentScan 注解的类。

      1. 创立 ClassPathBeanDefinitionScanner 对象。
      2. 设置 BeanNameGenerator \ ScopedProxyMode \ ScopeMetadataResolver \ ResourcePattern \ IncludeFilter \ ExcludeFilter \ BeanDefinitionDefaults .
      3. 解析注解中的 basePackages \ basePackageClasses .
      4. 进入 doScan().
      5. 加载每个 package,将获取到的 metadataReader 作为创立 ScannedGenericBeanDefinition 的参数。
      6. 判断 ScannedGenericBeanDefinition 是否有被@Component注解,合乎的放入办法后果集中。
      7. 遍历后果集。
      8. 判断是否实现 AbstractBeanDefinition,调用postProcessBeanDefinition进行解决。
      9. 判断是否实现 AnnotatedBeanDefinition,调用AnnotationConfigUtils.processCommonDefinitionAnnotations()进行解决。
      10. 依据BeanDefinition的抵触处理结果注册BeanDefinition.
      11. 从加载到BeanDefinition中过滤是否有@Configuration标注的类,有的话间接调用parse().
    9. processImports() 解决标有 @Import 注解的类。

      1. 判断是否有循环导入的问题
      2. 解决导入的类实现ImportSelector 接口

        1. 加载被导入的类。
        2. ParserStrategyUtils.instantiateClass() 将注解解析为 ImportSelector 对象 selector。
        3. 若 selector 实现了 DeferredImportSelector,间接放入deferredImportSelectorHandler。
        4. 递归解决导入类上的@Import。
      3. 解决导入的类实现ImportBeanDefinitionRegistrar 接口

        1. 加载被导入的类。
        2. ParserStrategyUtils.instantiateClass() 将注解解析为 ImportBeanDefinitionRegistrar 对象 registrar。
        3. 增加到 ImportBeanDefinitionRegistrar 中,在@Configuration注解解析实现后再进行加载。
      4. 解决导入的其余类

        1. 间接应用 processConfigurationClass 解决。
    10. addImportedResource() 解决标有 @ImportResource 注解的类。

      1. AnnotationConfigUtils.attributesFor() 解析出 AnnotationAttributes importResource 。
      2. 将解析出的resource 放入 ImportedResource 中。
    11. addBeanMethod() 解决标有 @Bean 注解的办法。

      1. 获取类中应用@Bean的办法 应用Java反射和ASM获取两遍,并进行比拟办法数量和办法名字的比拟。
      2. 比拟通过的办法放入后果集中。
      3. 将后果集一一放入BeanMethod
    12. processInterfaces() 解决接口的默认办法。

      1. 解决继承的抽象类非形象办法或者接口的默认办法
      2. 将父类或者实现的接口中的@Bean标注的办法放入 BeanMethod
      3. 循环解决父类或者父接口.
    13. 解析 superclass.

      1. 解决父类,间接返回循环解决.
  8. this.deferredImportSelectorHandler.process() 开始解决提早导入队列.

    1. 将队列中的ImportSelector一一放入 DeferredImportSelectorGroupingHandler.registry()
    2. 实现逻辑较简单,后续会持续剖析.
  9. ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()

    1. registerBeanDefinitionForImportedConfigurationClass

      1. new AnnotatedGenericBeanDefinition(metadata) 构建 BeanDefinition 对象.
      2. 获取 BeanDefinition 中的 scopeMetadata, 经 scopeMetadataResolver.resolveScopeMetadata()解决 设置BeanDefinition的scope
      3. importBeanNameGenerator.generateBeanName() 生成BeanName.
      4. AnnotationConfigUtils.processCommonDefinitionAnnotations()
      5. 注册BeanDefinition.
    2. loadBeanDefinitionsForBeanMethod
    3. loadBeanDefinitionsFromImportedResources
    4. loadBeanDefinitionsFromRegistrars
  10. 比照parse前后的registry中的BeanDefinition数量,将未解决的BeanDefiniton持续解决.
  11. Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes