关于后端:Spring-Framework-IOC-原理

44次阅读

共计 12971 个字符,预计需要花费 33 分钟才能阅读完成。

原因

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

正文完
 0