spring是一个框架,同时是一个容器,还是一个生态!。
spring默认是单例的,支持循环引用。改为多例时,不支持。scope=“prototype”
1.bean生命周期
class —> 实例化 —> 对象 —> 属性填充(依赖注入:@Autowired的属性赋值) —> 初始化 —> AOP —> bean —> 销毁
初始化:
①实现接口InitializingBean 重写afterPropertiesSet
②任意方法添加注解@PostConstruct
AOP:
判断当前对象是否需要AOP:
先去spring的容器中,找所有切面的bean,看当前对象是否有切点execution。
AOP的实现逻辑,是创建一个代理对象,由代理对象继承原对象,然后重写原对象的方法,然后执行aop的切点逻辑。
2.循环依赖
单例模式下:先把两个对象创建出来,然后set方法进行属性注入
多例模式下:创建A的时候,判断是否有依赖,有的话先不创建A,先去创建B对象,创建B时判断。。所以都不能创建。因为多例的模式下都是重新创建bean对象,不使用缓存,所以spring没有解决循环依赖问题。
默认spring没有解决构造函数的循环依赖,但是可以通过@Lazy注解,懒加载的方式,解决循环依赖问题。
spring容器创建对象:
如果要关闭循环依赖:
三级缓存:
为什么需要三级缓存?
三级缓存中存储的是lambda表达式,函数式接口,只有在产生循环依赖的时候才会执行lambda,否则不执行。
如果没有AOP或者说没有其他后置处理器,就不需要三级缓存。
1、singletonObjects:缓存某个beanName对应的经过了完整生命周期的bean
2、earlySingletonObjects:缓存提前拿原始对象进行了AOP之后得到的代理对象,原始对象还没有进行属性注入和后续的BeanPostProcessor等生命周期。多重循环依赖时,避免重复创建动态代理(有AOP的时候)
3、singletonFactories:缓存的是一个ObjectFactory,主要用来去生成原始对象进行了AOP之后得到的代理对象,在每个Bean的生成过程中,都会提前暴露一个工厂,这个工厂可能用到,也可能用不到,如果没有出现循环依赖依赖本bean,那么这个工厂无用,本bean按照自己的生命周期执行,执行完后直接把本bean放入singletonObjects中即可,如果出现了循环依赖依赖了本bean,则另外那个bean执行ObjectFactory提交得到一个AOP之后的代理对象(如果有AOP的话,如果无需AOP,则直接得到一个原始对象)。
4、其实还要一个缓存,就是earlyProxyReferences,它用来记录某个原始对象是否进行过AOP了。
原理:
3.IOC Inversion of Control
控制反转,作用是削减代码间的耦合。实现是利用工厂设计模式
控制了对象创建的权利,原:对象由程序员new,现:spring创建对象。
ioc容器包括bean工厂、后置处理器、单例缓存池、bean定义等多个组件组成。
IOC实现机制:
工厂 + 反射 (beanFactory.getBean() + 创建对象时反射)
refresh() 方法
AbstractApplicationContext类的refresh方法重点
// Prepare this context for refreshing.
// 容器刷新前的准备工作: 无关痛痒
// 设置容器的启动时间,活跃状态设为true,关闭状态false,
// 获取Environment对象,并加载,准备监听器和事件集合对象
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 创建容器对象(bean工厂):DefaultListableBeanFactory
// 加载xml配置文件的属性到当前工厂中,loadBeanDefinitions(beanFactory)
// 最重要的就是包装好BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// beanFactory的准备工作,对各种属性进行填充
prepareBeanFactory(beanFactory);
// ----------------------------
// Allows post-processing of the bean factory in context subclasses.
// 子类覆盖方法做额外的处理。一般不做任何扩展工作 空的模板方法
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
// 调用各种beanFactory处理器。 ----- BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册bean处理器,这里只是注册功能呢,真正调用是在getBean方法--BeanPostProcessor
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
// 为上下文初始化message源,即不同语言的消息体,国际化处理
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件监听多路广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 留给子类来初始化其他的bean 空的模板方法
onRefresh();
// Check for listener beans and register them.
// 在所有注册的bean中查找listener bean,注册到消息广播器中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的 非懒加载的单例对象 实例化操作,设置属性值
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,
// 同时发出ContextRefreshEvent通知别人
finishRefresh();
4.DI Dependency Injection
依赖注入
IOC 和 DI 的区别:IOC解耦,由IOC容器创建对象。DI是IOC的一个实现,是实现IOC的重要一环,只有注入了对象,才是创建了对象。
5.注解
@Configuration
该类等价 与XML中配置beans,相当于Ioc容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean,与xml中配置的bean意思一样。@Configuration注解的类必需使用 < context:component-scanbase-package=”XXX”/>扫描.
@ComponentScan
6.BeanFactory 作用
BeanFactory是顶层接口,主要职责就是生产bean,实现了简单工厂的设计模式。最强大的工厂是:DefaultListableBeanFactory
7.AOP
原理:动态代理。用于将与业务无关,但对多个对象产生影响的公共行为和逻辑的代码,抽取并封装为一个可重用的模块。作为切面
AOP的时候,内部调用,当前类的其他方法的时候,会导致AOP失效。也就是在A方法内部调用B方法的时候,B方法不会被增强。解决:1.将动态代理的对象手动注入一下。2.在线程中暴露代理对象 @EnableAspectJAutoProxy(exposeProxy = true) 存在本地线程ThreadLocal中,然后内部调用的时候,AopContext.currentProxy()。