当前位置: 首页 > news >正文

Spring Refresh

基本信息:
官方文档https://spring.io/projects/spring-framework
githubhttps://github.com/spring-projects/spring-framework/tree/v6.0.0
version6.0.0-SNAPSHOT

基于XML形式

public static void main(String[] args) throws NoSuchMethodException {ApplicationContext ac = new ClassPathXmlApplicationContext("aaa.xml");
}

总结

私认为包含了以下比较重要的阶段

  1. DefaultListableBeanFactory 创建
  2. 加载 BeanDefinition
  3. 执行 BFPP
    1. 这里还有一部分的 BeanDefinition
  4. 实例化
  5. 循环依赖
  6. 属性填充
  7. Aware 接口
  8. BPP:before
  9. initMethod
    1. InitializingBean
  10. BPP:after

比较重要的一些点:

  • 生命周期
  • IOC
  • AOP
  • 循环依赖
  • 自动装配

创建 ClassPathXmlApplicationContext 对象

ClassPathXmlApplicationContext 的构造方法:
refresh 在这个构造方法内,但因方法内容太多,所有与这里同级

一、super(parent);

跳转到顶级父类 AbstractApplicationContext:

  1. 创建变量 shouldIgnoreSpel
    1. 用于判断是否开启 Spel 表达式转换
  2. 通过日志工厂产生日志对象
    1. 用于记录日志
  3. 为容器创建上下文唯一标识
  4. 创建显式名称,与唯一标识一致
  5. 创建 beanFactoryPostProcessor 集合,用于存放 beanFactoryPostProcessor
    1. beanFactoryPostProcessor 作用:用于修改 BeanFactory 信息
  6. 创建活动标志位,
    1. 用于标记容器是否处于活动中
  7. 创建关闭状态标志位
  8. 创建锁 startupShutdownMonitor
    1. 保证 refresh 和 destroy 不被打断
  9. 创建 ApplicationStartup
    1. 检测应用启动阶段
  10. 创建监听器集合
  11. 观察者模式相关
  12. 使用构造方法创建资源模式管理器
  13. 创建一个 PathMatchingResourcePatternResolver 对象
    1. 用于解析 xml 配置文件
  14. 设置父容器
  15. 但此时为空

会跳转到 AbstractXmlApplicationContext,是祖宗的其中一个

  1. 设置验证标志为 true
    1. 是否需要对 xml 进行检测

二、setConfigLocations

设置配置路径,用于解析文件名中的占位符,如 spring-#{username}.xml -> spring-p’c.xml
调用 resolvePath 方法解析占位符的内容

getEnvironment().resolveRequiredPlaceholders(path)

真正进行解析工作的方法。

getEnvironment()

用户获取环境对象,如果目前的环境对象为空,则进行创建,同时会创建 解析器,用于下一步的解析工作

  1. 用 createEnvironment 进行创建
    1. 创建 StandardEnvironment 对象
      1. 此处会执行 StandardEnvironment 父类 AbstractEnvironment 的构造方法
        1. 创建 PropertySourcesPropertyResolver
          1. 属性资源解析器
        2. 调用 customizePropertySources 创建环境对象。
          1. systemProperties:环境标量
          2. systemEnvironment:系统变量

resolveRequiredPlaceholders

对占位符进行解析

  1. 进行解析 this.propertyResolver.resolveRequiredPlaceholders
    1. PlaceholderHelper 为空则会进行创建
      1. 用于解析和替换占位符
    2. doResolvePlaceholders 真正进行解析工作
      1. Placeholders.replacePlaceholders
        1. 解析
      2. 最终由 parseStringValue 完成占位符替换工作
        1. 递归获取到最内的内容,然后进行替换工作

Refresh(标志位)

核心!!!!
首先会进行上锁操作,使用的是前面创建的 startupShutdownMonitor
然后会使用 applicationStartup 来记录启动状态,同样是前面创建的

prepareRefresh

主要是做一下准备工作 - 初始化容器状态

1.设置容器启动时间:
this.startupDate = System.currentTimeMillis();
2.设置关闭状态
this.closed.set(false);
3.设置活跃状态
this.active.set(true);
4.属性拓展:可以自定义或替换 Environment 的值
initPropertySources();
5.对新增加属性进行验证 对上一步的操作进行校验
getEnvironment().validateRequiredProperties();
6.创建监听器集合  观察者模式
this.applicationListeners.addAll(this.earlyApplicationListeners);
7.创建事件集合  观察者模式
this.earlyApplicationEvents = new LinkedHashSet<>();

obtainFreshBeanFactory

初始化工厂,加载 BeanDefinition
AbstractRefreshableApplicationContext#refreshBeanFactory 为主要部分,因此后续的是此方法。

//如果已经存在Bean工厂,销毁并关闭该工厂
// 保证工厂是最新的
if (hasBeanFactory()) {destroyBeans();closeBeanFactory();
}
try {//创建Bean工厂DefaultListableBeanFactory beanFactory = createBeanFactory();//设置序列化idbeanFactory.setSerializationId(getId());//定制Bean工厂 如是否允许被覆盖同名不同定义的对象(是否允许对同名的Bean进行覆盖),以及是否允许Bean之间的循环依赖customizeBeanFactory(beanFactory);//加载BeanDefinitions  加载定义属性值    复杂  大量的重载方法loadBeanDefinitions(beanFactory);  //xml属性内的bean会被加载等等。//将新创建的Bean工厂赋值给类中的变量。this.beanFactory = beanFactory;
}

createBeanFactory - 创建 BeanFactory

主要是创建 DefaultListableBeanFactory 对象
DefaultListableBeanFactory 的构造方法,会加载父类,完成一些属性的初始化工作
同时在其父类 **AbstractAutowireCapableBeanFactory ** 的构造中,会忽略三个 Aware 类

  • BeanNameAware
  • BeanFactoryAware
  • BeanClassLoaderAware

customizeBeanFactory - 定制化操作(自定义一些参数)

主要是两个操作

  1. 能否覆盖同名称的不同对象
    1. 由参数 allowBeanDefinitionOverriding 控制
    2. 默认为 true
  2. 是否允许循环依赖
    1. 由参数 allowCircularReferences 控制
    2. 默认为 true

loadBeanDefinitions - 加载 BeanDefiniton !!!!

此处仅仅加载以下两种形式的 BeanDefinition,@ComponentScan 注解扫描的包内的类,在 invokeBeanFactoryPostProcessors 处加载。

  • xml 内编写的 Bean
  • 使用 扫描的包内含有 @Component 注解的类。

主要分为两个阶段

  1. 获取 Reader
    1. 用于读取 xml 文件
  2. 使用 loadBeanDefinitions 进行加载。
    1. 获取配置源,即XML
    2. 使用 XmlBeanDefinitionReader 对 XML 进行解析操作。
    3. 后续会有一大堆重载的 loadBeanDefinitions 方法,因此直接跳到最终的执行方法

最终的 loadBeanDefinitions – XmlBeanDefinitionReader#loadBeanDefinitions

  1. 通过 EncodedResource 对象,对xml 进行加载

    1. inputStream
    2. 转换成 InputSource
  2. 通过 XmlBeanDefinitionReader#doLoadBeanDefinitions 完成真正的加载。

  3. ** — XmlBeanDefinitionReader#doLoadBeanDefinitions**

  4. 通过 XmlBeanDefinitionReader#doLoadDocument 将 InputSource 转换成 Document 对象

    1. Document 对象是一个类似于链表的结构。
    2. 通过 DocumentBuilderFactory 创建 DocumentBuilder,使用 parse 方法,完成对 inputSource 的解析
  5. 再通过 XmlBeanDefinitionReader#registerBeanDefinitions 完成 Beandifiniton 的注册。

  6. ** — XmlBeanDefinitionReader#registerBeanDefinitions**

  7. 创建 BeanDefinitionDocumentReader ,用于解析 Document – 通过反射

    1. 此处还会获取已经存在的BeanDefinition 用于后续比对
  8. — BeanDefinitionDocumentReader#registerBeanDefinitions – 完成解析 Document 并进行注册

  9. BeanDefinitionDocumentReader#doRegisterBeanDefinitions – 真正的干活方法

  10. 创建 BeanDefinitionParserDelegate – 用于解析节点信息

  11. 解析 profile 标签 – 多见于 SpringBoot

  12. parseBeanDefinitions – 解析 BeanDefinitions

  13. 遍历所有的阶段信息,分为两种处理方式

  14. 内置标签 – import、alias、bean、beans – parseDefaultElement
    1.

  15. 自定义标签 – 需要自定义类,实现 BeanDefinitionParser 接口 — delegate.parseCustomElement

    1. 此处是 ComponentScan 标签
    2. — BeanDefinitionParserDelegate#parseCustomElement – 最终到了这里
    3. 获取命名空间 – 方法开始
    4. 根据命名空间获取 NamespaceHandler – NamespaceHandlerSupport
    5. 调用 NamespaceHandlerSupport#parse 进行解析
    6. 获取 BeanDefinitionParser – ComponentScanBeanDefinitionParser
    7. — 调用 ComponentScanBeanDefinitionParser#parse
    8. 创建 ClassPathBeanDefinitionScanner
    9. — 调用 ClassPathBeanDefinitionScanner#doScan 完成对某个包的解析
      1. 遍历包内的所有类,获取标注有 @Component 注解的类
      2. 检查是否注册过
      3. 创建 BeanDefinitionHolder,是 BeanDefinition 的包装类
      4. registerBeanDefinition – 注册 BeanDefinition,注册的是 BeanDefinitionHolder、
      5. — BeanDefinitionReaderUtils.registerBeanDefinition – 执行注册
      6. 获取 BeanName
      7. 通过注册器 DefaultListableBeanFactory 注册
        1. DefaultListableBeanFactory – 实现了 BeanDefinitionRegistry 接口,用于对 BeanDefiniton 信息的管理
        2. 实际是将 BeanDefinition 放置进 beanDefinitionMap
          1. key:beanName,value:beanDefinition
        3. 同时将 BeanName 放入 beanDefinitionNames 中
      8. 如果有别名,也会将其放置到 map 中 – aliasMap
    10. 一直返回,完成。

prepareBeanFactory

初始化 BeanFactory,做一些准备工作
主要是设置一些属性

// Tell the internal bean factory to use the context's class loader etc.
//设置类加载器  没有则设置默认类加载器
beanFactory.setBeanClassLoader(getClassLoader());
//判断是否忽视SpEL表达式 默认值为false
if (!shouldIgnoreSpel) {// 设置 beanFactory 的表达式处理器beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
// 为 beanFactory 增加一个默认的 PropertyEditor
// 主要是对 bean 的属性等设置管理的一个工具类
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//配置Bean工厂
// Configure the bean factory with context callbacks.
// 添加Bean后处理器
// ApplicationContextAwareProcessor 用来完成某些Aware对象的注入
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//ignoreDependencyInterface 设置忽略的aware接口   忽略对应接口的实现
//aware 获取容器或者系统的某些对象
//初始化阶段会专门对这些进行设置。 BPP.before 时已经完成注入    即 上方 ApplicationContextAwareProcessor 对象
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//手动注册Bean(依赖)
// 设置几个自动装配的特殊规则,当ioc进行初始化时,如果存在多个实现,则使用指定对象注入。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
// 注册 BPP
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 增加对 AspectJ 的支持,在 Java 中织入分为三种方式,分别为编译器织入,类加载器织入,运行期织入,编译器织入是指在 Java 编译器,采用特殊的编译器,将切面织入到类中
// 而类加载期织入则指通过特殊的类加载器,在类字节码加载到 JVN 时,织入切面,运行期织入则是采用 cglib 和 jdk 进行切面的织入
// AspectJ 提供了两种织入方式。第“种是通过特殊编译器,在编译器,将 AspectJ 语言编写的切面类织入到 Java 类中第二种是类加载期织入,就是下面的 load time weaving,
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}

postProcessBeanFactory

空的拓展点,web代码有具体实现

invokeBeanFactoryPostProcessors

实例化和 执行 所有已注册的 BeanFactoryPostProcessor,自动配置在此处, @ComponentScan,也是在此处
核心只有一个 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
主要处理实现了 BeanDefinitionRegistryPostProcessor 接口和 BeanFactoryPostProcessor 接口的类

BeanDefinitionRegistryPostProcessor主要是针对 BeanFactory 的管理,同时包括了 BeanDefinition
BeanFactoryPostProcessor主要是针对 BeanDefinition 信息的管理

方法中主要分为三类处理

  1. 通过参数传递进来的
  2. 实现了 BeanDefinitionRegistryPostProcessor 接口的 – 内部的
  3. 实现了 BeanFactoryPostProcessor 接口的 – 内部的
  4. 执行的顺序看是否实现了 Ordered 相关注解
    1. PriorityOrdered > Ordered > other

此方法的核心处理逻辑主要是以下两个方法:
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
BeanFactoryPostProcessor#postProcessBeanFactory

BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry

以下是 ConfigurationClassPostProcessor 实现类的 postProcessBeanDefinitionRegistry 方法

ConfigurationClassPostProcessor#processConfigBeanDefinitions

  1. 获取所有的 BeanName
  2. 遍历所有的 BeanName 获取 BeanDefinition
    1. 如果没有被加载过的,会放到一个 list 中
  3. 获取 ConfigurationClassParser 解析器
    1. 用于解析注解
  4. ConfigurationClassParser#parse
    1. 遍历每一个 BeanDefinition
    2. 解析操作 – parse --> processConfigurationClass
      1. @Conditional – 是否跳过
      2. @Import – 是否被引用,同时会避免重复导入的情况
      3. **ConfigurationClassParser#doProcessConfigurationClass **
        1. 是否被 @Component 标注
          1. 会有递归查询所有的被修饰的
        2. @PropertySource
        3. @ComponentScan、@ComponentScans
          1. 扫描包下所有需要被注入容器的类,并生成 BeanDefinition
          2. 通过 ComponentScanAnnotationParser#parse
          3. 也会存在递归
        4. @ImportResource
          1. 一般很少
        5. 检索 @Bean 注解
          1. 解析父类,如果有的话
  5. DeferredImportSelectorHandler#process
    1. DeferredImportSelectorGroupingHandler#processGroupImports
      1. DeferredImportSelectorGrouping#getImports
        1. AutoConfigurationGroup#process – 此处是 Spring Boot 的
          1. AutoConfigurationImportSelector#getAutoConfigurationEntry
            1. 获取 spring.factories 内的 KV – getCandidateConfigurations
              1. 解析 spring.factories 文件,获取所有的 BeanNamew
            2. 移除重复
            3. 过滤 – getConfigurationClassFilter().filter(configurations);
              1. 基于 spring-autoconfigure-metadata.properties 文件
            4. 包装成 AutoConfigurationEntry 返回
  6. end

BeanFactoryPostProcessor#postProcessBeanFactory

暂无

registerBeanPostProcessors

实例化和注册所有的 BeanPostProcessors,仅仅是注册

PostProcessorRegistrationDelegate#registerBeanPostProcessors

  1. 获取所有实现了 BeanPostProcessor 接口的 BeanName
  2. 按顺序进行处理 PriorityOrdered > Ordered > other > 内部
  3. getBean(BeanPostProcessorName)
  4. addBeanPostProcessors

initMessageSource

国际化

initApplicationEventMulticaster

初始化多播器,观察者模式

onRefresh

初始化特殊的 Bean,是一个空实现,SpringBoot 内有具体实现

registerListeners

找到监听器并注册,绑定多播器和监听器
发布早期时间 – SimpleApplicationEventMulticaster#multicastEvent

finishBeanFactoryInitialization – 核心!!!

Bean的最终处理阶段,核心阶段,包括了实例化,初始化,自动配置,循环依赖,代理创建,InitializingBean(主要完成对一些属性的初始化,实现了 InitializingBean 接口的)

DefaultListableBeanFactory#preInstantiateSingletons

实例化非懒加载的 Bean

  1. 获取 BeanDefinitonName
  2. 合并 BeanDefiniton
    1. 主要检查 cache 中有没有
  3. 只处理特定类型的 Bean
    1. 非抽象
    2. 单例
    3. 非懒加载
  4. 判断是否为 FactoryBean
    1. 实现方式
      1. https://www.yuque.com/hanpiyu/bquwpm/kcc15tgl8wo57ou7#bpOeq
    2. 使用 “&” + beanName 获取实现了 FactoryBean 接口的类
    3. 实际获取中,通过实现了 FactoryBean 接口的 Bean 的getObject 获取对象
    4. 即 Spring 的一级缓存中,不存在 由 FactoryBean 加载的 Bean
    5. 加载出来的 Bean 会存放在另外的 map 中。factoryBeanObjectCache
  5. AbstractBeanFactory#getBean -> AbstractBeanFactory#doGetBean
    1. 获取 BeanName by transformedBeanName
    2. 先进行一次获取,排除预先加载的Bean,或者是获取 FactotyBean
      1. 此处就包含了 FactotyBean 的获取流程
    3. 如果正在创建中,则抛出异常
    4. 获取父容器
      1. Spring MVC 中可见
      2. 会尝试从父容器中获取
    5. 合并 BeanDefiniton
    6. 检查 DependsOn
      1. 如果有依赖,则优先创建依赖
    7. **创建 Bean – DefaultSingletonBeanRegistry#getSingleton **
      1. 此处会传入一个函数式接口,当执行到函数式接口的方法时,会调用传入的 lambda 表达式
      2. 实现方式:基础的实现方式
      3. AbstractAutowireCapableBeanFactory#createBean
        1. 获取 Class 对象 by BeanName
        2. 针对于 lookup-method、replace-method 进行操作 AbstractBeanDefinition#prepareMethodOverrides
          1. 会产生覆盖
          2. 在一个单例Bean下引用一个原型(prototype)模式的Bean,需要引用 lookup-method标签,否则取的是同一个
        3. 使用代理创建对象 – InstantiationAwareBeanPostProcessors 接口
          1. InstantiationAwareBeanPostProcessors 针对于实例化前后的。
          2. 如果返回的是普通对象,则拦截方法无法得到执行。
          3. 必须执行 postProcessBeforeInstantiation
          4. 才能执行postProcessAfterInitialization
          5. 此处是一个拓展点,供由用户实现,默认的实现方式的 BPP:after
        4. 创建 Bean – AbstractAutowireCapableBeanFactory#doCreateBean
          1. 如果该 Bean 已经存在,则删除

            1. 容器加载完成后,再 getBean,是无法进入此处的,单例时
          2. Bean 实例化 – AbstractAutowireCapableBeanFactory#createBeanInstance
            1.

          3. 如果不是 NullBean 类型,则修改目标类型

          4. 修改合并的BeanDefinition – applyMergedBeanDefinitionPostProcessors --> CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

            1. 包含了对 @PostConstruct 和 @PreDestroy 等一些注解的处理
            2. CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
              1. 针对@PostConstruct 、@PreDestroy、@Resource
          5. 循环依赖处理

            1. 判断是否开启了循环依赖,在最开始的时候有加载 --customizeBeanFactory 方法
            2. 放入三级缓存 - DefaultSingletonBeanRegistry#addSingletonFactory
              1. 三级缓存:key:beanName,value:函数式接口 ObjectFactory
              2. 检查一级缓存
                1. 如果已经有了,则不做处理
              3. 放入三级缓存
              4. 删除二级缓存内的
              5. 增加到注册列表中
          6. 属性填充 – AbstractAutowireCapableBeanFactory#populateBean

            1. 修改 Bean 的状态 – InstantiationAwareBeanPostProcessors#postProcessAfterInstantiation
              1. 此处是 after ,前面是 before
              2. 此种场景是 before 没有实现
            2. 获取 PropertyValues —
            3. 判断自动装配的类型 – 默认是 byType
              1. 有则用,无则加载
              2. AbstractAutowireCapableBeanFactory#autowireByName
                1. 属性过滤
                  1. 排除简单类型、无 setter 方法、pvs 没有该属性名、未被排除
                2. 根据属性名获取 Bean
                3. 添加到 MutablePropertyValues 中
                4. 注册 propertyName 和 BeanName 的依赖关系
              3. AbstractAutowireCapableBeanFactory#autowireByType
                1. 获取类型转换器,如果有自定则使用自定义,无则使用默认的
                2. 属性过滤
                  1. 排除简单类型、无 setter 方法、pvs 没有该属性名、未被排除
                3. 获取属性描述信息
                4. 获取 setter 方法的参数包装对象 – methodParam
                  1. 包装了参数
                5. 将 methodParam 封装成 DependencyDescriptor
                6. 根据 DependencyDescriptor 匹配候选 Bean 对象
                7. 添加到 MutablePropertyValues 中
                8. 注册依赖关系
            4. 是否拥有 instantiationAwareBeanPostProcessors
              1. 属性注入
            5. 是否需要依赖检查
            6. 设置属性值 – AbstractAutowireCapableBeanFactory#applyPropertyValues
              1. 通过反射设置值
          7. 初始化 – AbstractAutowireCapableBeanFactory#initializeBean

            1. 执行 aware 接口 – AbstractAutowireCapableBeanFactory#invokeAwareMethods

              1. 设置一些值,如果 Bean 实现了这些 Aware 接口
              2. BeanNameAware
              3. BeanClassLoaderAware
              4. BeanFactoryAware
            2. BeanPostProcessor#postProcessBeforeInitialization
              1.

            3. invokeInitMethods

              1. 调用所有的 InitializingBean#afterPropertiesSet
                1. MVC 中,使用了这个对一些集合进行初始化工作
              2. 执行自定义 init 方法
            4. BeanPostProcessor#postProcessAfterInitializationr

              1. 动态代理的创建
              2. 如果创建了代理,则代理对象会取代普通对象
          8. 放入 map 中,方法后续销毁使用 – registerDisposableBeanIfNecessary

      4. 放入一级缓存中,返回 Object
        1. 放入一级缓存
        2. 删除二三级缓存
        3. 添加 registeredSingletons 中,表明已经注册

finishRefresh

完成整体的刷新,会广播事件,Spring MVC 中,就会利用观察者模式在此处完成对九大组件的初始化工作。

特殊部分 – 待补

循环依赖

A 依赖 B,B 依赖 A,在初始化的时候,需要属性注入,此时就会发生死锁。
Spring 中设计的三级缓存,
一级缓存用于存储成品对象,
二级缓存用于存储半成品, // 作用不大?
因为会进行两次的代理生成,如果没有二级缓存,则会发生多个代理对对象的情况。
三级缓存存储了一个匿名内部类
三级缓存是为了解决 Spring 中,存在代理的情况下发生的循环依赖
即无代理的情况下,二级缓存既可以解决问题。
在发生代理的时候,代理对象会取代了原对象,因此只使用二级缓存,无法解决循环依赖

状态流转

开启了循环依赖的前提

  1. 将匿名内部类放入三级缓存中,包含了实例化的Bean
  2. 判断是否需要提前暴露
    1. 单例
    2. 开启了循环依赖
    3. Bean 正在创建
  3. 依次去一二三级缓存中
  4. 一直到三级缓存,此时判断是否需要动态代理
    1. 如果不需要则返回原对象
    2. 通过标志位进行判断
  5. 删除三级缓存中的,并把对象方法二级缓存中
  6. 判断是否进行了增强
    1. 没有增强则原对象
  7. 然后会把最终对象方法一级缓存中,并且删除二三级缓存

AOP

面向切面编程。将与业务无关的逻辑抽取出来,

自动装配

byName

byType

自动配置

非默认的 Bean 创建方式

FactoryBean

观察者模式 – 事件驱动型

拓展点

一些Spring 提供的拓展点


http://www.taodudu.cc/news/show-7669516.html

相关文章:

  • EIGRP的优势分析
  • EIGRP基础
  • CCNP 3 EIGRP
  • EIGRP综合实验解析
  • CCNA 6 EIGRP
  • EIGRP总结
  • EIGRP回顾
  • 3.4.2 CSMA/CD协议
  • CSMA 简介
  • 以太网 CSMA-CD与CSMA-CA的区别与工作方式
  • 【基础】static搭配inline 味道更佳(explicit_bzero-rawmemchr)
  • bzero 和 memset 的区别
  • bzero()
  • ModuleNotFoundError: No module named ‘sklearn‘
  • 成功解决ModuleNotFoundError: No module named ‘torchtext.legacy‘
  • ModuleNotFoundError: No module named ‘selenium
  • No module named ‘pyautogui‘
  • No module named ‘dataclasses‘
  • 【python基础】python导包显示No module named XXX问题
  • 记录-centos7搭建DNS服务(named.servicenamed-chroot)全流程
  • linux启动named服务失败,处理service named start失败failed_dns
  • 解决No module named pip问题
  • JPA的@NamedQuery注解
  • 解决No module named tkinter
  • ModuleNotFoundError: No module named ‘sklearn‘解决方案
  • No module named torchcrf
  • No module named SimpleHTTPServer
  • No module named ‘cv2‘ 解决办法 (No module named ‘numpy‘ 等所有报错均可解决)
  • DNS域名解析服务--named使用
  • Linux名字服务器(named)简单配置