spring相关记忆点
- @Schedule 注解 是在beanPostProcess 的 postProcessAfterInitialization 中执行,Aop 也是在postProcessAfterInitialization中执行,不建议针对schedule的实现类进行切面,初步判断两者的顺序无法保证先后,不过正常情况都是先aop在schedule ,aop增强逻辑能正常应用到schedule的切点,不过尽量避免出现错误的可能性。一个案列:A是一个Schedule 的服务类,B是一个aop增强,适应的切点是A的方法和schedule注解,结果A的定时方法执行了,B的切面确没执行,原因 A 发生了循环依赖,导致A初始化是到aop 的postProcessAfterInitialization中判断了循环依赖,导致schedule 执行postProcessAfterInitialization时拿到的没有进行过aop的对象,移除A的循环依赖问题解决
- @PostConstruct InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization
- spring 使用三层缓存解决 循环依赖的问题:三级缓存的作用是为了解决spring中Bean依赖注入时发生的循环依赖。如果不需要AOP,那么只需要二级缓存即可实现,如果有AOP,其实二级缓存也能够实现,但是会打破Bean的生命周期,不符合spring的原则,因为需要把AOP对象放入二级缓存中,那么就必须在所有需要AOP处理的Bean对象初始化之前就对Bean对象进行后置处理(生成AOP对象),即使没有发生循环依赖!这并不是spring想看到的,所以spring引入了三级缓存,而且存入的是<beanName, ObjectFactory>结构,ObjectFactory是一个lambda表达式,相当于一个回调函数,当发生循环依赖的时候,会进行lambda表达式的执行,获取到Bean对象或者 AOP代理对象,再将Bean对象或者 AOP代理对象存入二级缓存中,如果之后还有循环依赖指向该对象(类似 A 依赖 B , B 依赖 A和C , C 依赖 A这种情况),就直接从二级缓存里面获取,从而解决了循环依赖。(这里解释了为什么不直接在二级缓存里存放lambda表达式,因为同一个lambda表达式每执行一次,就会生成一个新的代理对象,不能保证单例)。
- InitializingBean.afterPropertiesSet 是在所有postProcessBeforeInitialization 执行后执行,也就是afterPropertiesSet 在@PostConstruct 之后执行