spring bean

49 阅读6分钟

1 核心组件

1.1 bean组件

bean 组件 完成3件事 1.bean的定义 配置bean的信息,(通过xml 注解),加载成一种规范。bean 定义 2.bean 的创建 加载成beandefinition后, bean 的创建 通过beanfactory 根据beandefinition 信息创建bean, 用到反射 ,工厂模式。 3.bean 的解析 bean 的生命周期, 填充属性 初始化操作,是否实现一些接口。 创建是典型的工厂模式 , 顶级接口 beanFactory beanFactory.getBean("userService"); 工厂模式的体现: 根据参数不同,生产出不同的对象。


beanFactory 顶级接口 最终实现 DefaultListableBeanFactory spring在创建beanfactory时的类型。


bean的定义:beandefinition < bean id="userDao" class="UserDao"> 解析bean 标签---->读取bean 信息---> 用beandefinition存储 (bean定义对象) ---->根据beanDefinition 信息完成对象创建。 图1 在a

1.2 context 组件

理解 1.构建在core beans 模块基础上,集成2个模块的特性。 2. context 有额外功能,国际化,资源加载等 3. applicationContext 是Context 顶级父类。applicationcontext 继承beanFactory (容器对象)。 beanFactory容器对象:提供对于bean基本操作能力。查找bean 存储bean。 applicationContext 也是容器对象 增强 : 事件发布,后置处理器注册等。

1.2.1 简述spring后置处理器

后置处理器 是一种拓展机制,贯穿bean的生命周期。可以对bean进行一些增强。 分为两类

beanFactoryPostProcessor

BeanFactoryPostProcessor接口介绍

对bean的beandefinition 信息修改。 BeanFactoryPostProcessor顾名思义bean工厂的后置处理器,它主要是对bean工厂做一些操作,他可以利用其中的postProcessBeanFactory方法对beanfactory做一些操作,同时他有一个比较厉害的实现类BeanDefinitionRegistryPostProcessor,这个抽象类继承了BeanfactoryPostProcessor,同时多定义了一个方法postProcessBeanDefinitionRegistry在这个方法中可以对BeanDefinaition做一些BeanDefination做一些增加修改操作。总之BeanFactoryPostProcess和其实现类都是对BeanFactory或者工厂中的BeanDefination做了一些操作,这些操作必须在bean实例化之前执行完成,因为在之后就没有任何意义了。

  • 和BeanPostProcessor原理一致,Spring提供了对BeanFactory进行操作的处理器BeanFactoryProcessor,简单来说就是获取容器BeanFactory,这样就可以在真正初始化bean之前对bean做一些处理操作。
  • 允许我们在工厂里所有的bean被加载进来后但是还没初始化前,对所有bean的属性进行修改也可以add属性值。

beanPostProcessor

spring容器实例化bean(反射调 构造方法后,未进行属性填充),在执行bean 的初始化方法前后,添加一些逻辑。 填充属性 ---->是否实现aware接口(实现,调用方法)--->beanpostprocessor (before 方法 针对创建出来的bean 完成一些操作)---->执行init-method方法 初始化bean ---->after方法(对bean 完成一些操作:如果配置aop 代理对象在after方法中产生)

2. ioc流程图

bean 填充属性时,会产生循环依赖。(A 依赖 B,B依赖A) 循环依赖。 通过set 方法注入产生的依赖 可以解决。 通过 构造器方法注入产生的依赖 不能解决。 在这里插入图片描述

3.ioc 源码

3.1 obtainFreshBeanFactory

// 重要:设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用 customizeBeanFactory(beanFactory); 默认都允许

3.1.1是否允许bean 覆盖

在这里插入图片描述 在两个文件中,加载id 相同的 bean ,如果设置允许bean覆盖,后加载的bean 会覆盖之前加载的bean

3.1.2 是否允许循环引用

在这里插入图片描述

4 循环依赖

其他人写的 spring 循环依赖

传统创建bean

af

beanPostProcessor 处理器里面有一个aop处理器--> 在aop 处理器(AspectJAwareAdvisorAutoProxyCreator)中 调用createProxy() 创建动态代理对象。 ac


aa述

实例化a对象后,添加factory(a) 在工厂池中, factory 只干一件事情,在创建动态代理的时候,使用方式二创建代理对象,调用getEarlyBeanReference() 提前处理 创建动态代理引用。 问?为什么不 创建完a对象的实例化之后,直接调用 提前引用? 提前引用:用于在a创建的过程当中,如果有对象引用a,才会执行提前引用,否则,factory(a) 不会被执行。 什么会提前引用a呢? 当给b对象填充 属性a时, 才会提前引用a,调用a里面的提起引用方法,

关键 创建工厂池,如果想获取动态代理之后的对象,那么可以调用工厂池里面,对象所绑定的工厂方法,从而动态的去提前创建动态代理对象。 如果创建对象过程中,不需要提前引用,factory(a)不会被调用,创建代理对象。 所谓的提前引用,指的是在创建的过程当中被提前引用。


对于对象之间的普通引用, 二级缓存会保存new出来的不完整对象,这样当单例池中找到不依赖的属性时,就可以先从二级缓存中获取到不完整对象,完成对象创建,在后续的依赖注入过程中,将单列池中对象的引用关系调整完成。 三级缓存:如果引用的对象配置了AOP,那在单例池中最终就会需要注入动态代理对象,而不是原对象。而生成动态代理是要在对象初始化完成之后才开始的。于是Spring增加三级缓存, 保存所有对象的动态代理配置信息。在发现有循环依赖时,将这个对象的动态代理信息获取出来,提前进行AOP,生成动态代理。


1、三级缓存各自的作用

第一级缓存存的是对外暴露的对象,也就是我们应用需要用到的

第二级缓存的作用是为了处理循环依赖的对象创建问题,里面存的是半成品对象或半成品对象的代理对象

第三级缓存的作用解决循环依赖中,代理对象创建过晚的问题。 提前创建代理对象。(可以但spring没做) 在newInstance 后直接创建代理。 只有发生循环依赖的时候才创建代理对象。

2、Spring 为什么要引入第三级缓存

严格来讲,第三级缓存并非缺它不可,因为可以提前创建代理对象

提前创建代理对象只是会节省那么一丢丢内存空间,并不会带来性能上的提升,但是会破环 Spring 的设计原则

Spring 的设计原则是尽可能保证普通对象创建完成之后,再生成其 AOP 代理(尽可能延迟代理对象的生成)

所以 Spring 用了第三级缓存,既维持了设计原则,又处理了循环依赖;牺牲那么一丢丢内存空间是愿意接受的。

问题: 为什么需要使用二级缓存 earlySingletonObjects? a 问题 只有一级缓存,三级缓存 能不能解决循环依赖? av