Spring bean的生命周期
bean的生命周期指的就是bean从创建到销毁的整个过程
1.实例化
- 通过反射去推断构造函数进行实例化
- 实例工程,静态工厂
2.属性赋值
- 解析自动装配
- 循环依赖的解决
3.初始化
- 调用xxx的aware回调方法
- 调用初始化生命周期的回调
- 如果bean实现aop,创建动态代理
4.销毁
- 在spring容器关闭时进行调用
- 调用销毁生命周期回调
单例bean的优势
- 单例只要创建一次,减少了创建实例的消耗。spring会通过反射或者cglib来生成bean实例,这都是消耗性能的操作
- 减少了内存等资源的消耗,提高了内存的利用率,减少了jvm内存回收的负担
- 我们获取也更快,除了第一次创建都是从缓存中获取(性能)
bean是线程安全的吗
- 单例bean的情况下 如果在类中声明成员变量 并且有读写操作 就会线程不安全(有状态)
- 如果我们把成员变量申明在方法中,那就是线程安全的(无状态)
还有什么方法解决线程安全问题?
- 设置为多例 @scope(prototype)
- 因为声明为多例了,使用的时候会新new一个,都是唯一的
- 将成员变量放在 ThreadLocal
- 同步锁 会影响吞吐量
Spring实例化bean有几种方式?
- 构造器方式(反射)
- 静态工厂的方式 factory-method
- 实例工厂方式 factory-bean + factory-method
- FactoryBean方式
区别 第一种是spring控制实例,234可以由程序员自己控制bean的实例化过程,更加灵活
什么是bean装配,自动装配?
将bean和bean的依赖互相关联起来
- 手动
- 自动 @Autowried ref="" 将bean自动装配
自动注入有什么限制吗
自动注入是通过Autowrie
- 一定要声明set方法
- 覆盖 仍然可以通过来定义配置,这些配置会自动覆盖
- 基本数据类型 不能自动专攻欸简单的数学,如基本数据类型,字符串和类 (手动注入可以 AValue)
- 模糊特性:自动装配不如显示装配精确,如果有可能精良使用显示装配
推荐使用 @Autowried ref=""
自动装配的方式有几种
- no 默认 不自动装配
- byName 根据bean的名字自动装配
- byType 通过参数的数据类型自动装配
- constructor 利用构造函数进行装配 并且构造函数用过byType进行装配
- autodetect 自动探测 如果由构造方法 通过construc的方式进行自动装配 否则使用byType的方式自动装配(在spring3.0+弃用)
bean有哪些生命周期回调方法?有哪几种实现方式?
- 通过注解的方式
- 创建@PostConstruct
- 销毁@PreDestroy
Spring在加载的过程中Bean有几种形态
- 概念态
- 定义态
- 纯净态
- 成熟态
Spring是如何解决bean的循环依赖?
关键 一定要有一个缓存保存它的早期对象作为死循环的出口
- 一级缓存 存储完整的bean
- 二级缓存 避免多次循环依赖
- 采用三级缓存解决的(三层map)
- 三级缓存时一个函数接口,可以把方法传进去(把bean的实例和bean的明治传进去)(后续可能会进行aop动态代理的创建)
- 不会立即调用
- 会在ABA(第二次调用getBean(A))才会去调用三级缓存(如果在实例化后立即调用的话:所有的aop 不管bean是否循环依赖都会在实例化后创建proxy)
- 然后放入二级缓存中(如果实现了aop才会创建动态代理,如果,欸写实现依然返回bean实例)
二级缓存能不能解决循环依赖?
- 如果只是死循环问题,一级缓存就可以解决,无法避免在并发情况下获取不到完整的bean
- 二级缓存可以解决循环依赖 只不过出现重复循环依赖 会多次创建aop的动态代理
Spring有没有解决多例bean的循环依赖?
- 多例bean不会使用缓存进行存储(多例bean每次使用都需要重新创建)
- 不缓存早期对象无法解决循环
Spring有没有解决构造函数参数Bean的循环依赖?
- 构造函数的循环依赖也是会报错的
- 可以通过@lazy (延迟加载注解)
- 就不会立即创建依赖的bean了,而是等到用到才通过动态代理进行创建
bean有哪些生命周期的回调方法?有哪几种实现方式?
生命周期的回调方法有两种,一种是初始化的时候调用,一种是销毁的时候调用
- 各有三种实现方式