—— IOC进阶)
一、Bean的生命周期创建就是执行new构造方法依赖注入/属性注入指的就是Autowired注解的这些变量从三级缓存里拿初始化算出来一些以后肯定会用到的东西用PostConstruct注解生命的方法在这个时候执行销毁。相当于把引用赋值为null就可以被回收了二、单例Bean的线程安全问题spring默认bean是单例的你可以认为“资源只有一份”比如某个Service类加了Service注解那么这个service的实例只有一份当很多个请求进来的时候都一起用这个实例就要考虑bean的线程安全问题。有这么几种防御式编程的手段synchronized关键字ThreadLocal除了static类变量、final变量、以及Autowired注入的变量之外。其余变量不许出现在成员变量里只能出现在每个方法的内部。修改作用域把单例改成prototype三、如何解决循环依赖问题循环依赖A类里用Autowired注入了B类的实例B类用Autowired注入了A类的实例解决方式借用spring的三级缓存底层逻辑是“提前暴露半成品”。一级放bean成品二级放未注入属性的半成品三级工厂库。主要解决AOP带来的问题创建完A的beanA先在三级缓存里放一个自己的A工厂实例准备依赖注入B的实例的时候于是去Spring一级缓存一直找到三级缓存找B发现B还没有被创建出来所以去实例化B。B实例经过创建阶段B也在三级缓存放一个自己的工厂实例但是因为本次叙述是A打头的所以没用到走入依赖注入阶段开始从缓存里找A的实例从一级缓存开始找一直找到三级缓存发现可以在三级缓存中通过对象工厂拿到A虽然A不太完善但是已经存在就把A放入二级缓存同时删除三级缓存中的A此时B已经完成注入了成为一个成品于是把B放入一级缓存。接着对A进行注入现在A可以从一级缓存拿到B了此时A也完成了注入成为了一个成品于是删除二级缓存里的A把A放入一级缓存。总感觉跟“分布式事务”、“两阶段提交”、“TCP三次握手”这些思想的底层逻辑有点像因为都有“半成品”出现。感觉第三级缓存就像是用来做标记用的。跟解决死锁的思路也很像3.1 为什么需要三级缓存因为A这个类可能被Transactional注解修饰或者自定义切面 Aspect 能匹配到 A 类中的方法也就是A生成的实例bean并不是原生的而是一个代理实例。如果只有一二级缓存的话B拿到的是原生实例而A最后生成并放到一级缓存里的是代理实例二者不一致了。所以B去获取A实例的时候就得获取一个反射的代理实例所以需要再来一个缓存专门存工厂。