1、加载配置,可以是xml配置或者是配置类,Spring提供了统一的抽象接口BeanDefinitionReader,对于不同的配置有不同的实现类,xml配置是使用XmlBeanDefinitionReader,然后将Bean解析成BeanDefinition对象,然后注册到beanDefinitionMap中,key就是bean的id,value就是BeanDefinition对象,如果有别名的话,在map额外保存一个key是别名,value是id,获取Bean的时候会重定向一次
2、Spring的事件传播器会接受相应事件并传播
DefaultListableBeanFactory
, public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
重要的属性:
benanClass
scope
isLazy
dependsOn
primary
:表示一个Bean是主Bean,在Spring中一个类型可以有多个bean对象,在进行依赖注入时,如果根绝类型找到了多个bean,此时会判断这些bean是否存在一个主bean,如果存在,直接将这个bean注入给属性
initMethodName
...
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
BeanFactotyPostProcessor
Bean工厂的后置处理器即获取工厂中的BeanPostProcessor,调用方法处理bean
1、扫描 ----> 创建BeanDefinition对象 ———>放到beanDefinitionMap中
2、验证
遍历beanDefinitionMap,验证类是否能被创建出来(是否是singleton 是否是抽象类,是否是懒加载,是否是FactoryBean接口的实现类 id属性是否合法 等等),将最终的Bean的id存到一个Set集合中(singleton类型的)
,这个Set集合的名字是SingletonsCurrentlyInCreation
当一个Bean的生命周期全部结束后,会将这个id移除掉,
3、得到Bean的class对象,根据注入模型,如果设置了构造模式就推断构造方法,判断要使用哪个构造方法进行创建对象,没有设置构造模式默认使用的就是无参的构造方法
4、得到构造器对象,使用反射
实例化对象
5、合并BeanDefinition,主要是合并有父类的bean
6、提前暴露一个bean工厂对象---->为了解决循环依赖
7、填充属性,对属性的注入
8、执行部分aware接口,比如ApplicationContextAware接口,为其注入ApplicationContext工厂,等 并执行实现BeanPostProcessor接口中重新的postProcessBeforeInitialization()方法
9、执行剩下的aware接口,并执行Bean的初始化方法
,即@PostConstruct
标注的方法
10、执行接口版和自定义xml配置版的初始化方法(即实现了InitializingBean接口重写的方法afterPropertiesSet())
11、执行实现的BeanPostProcessor接口的postProcessAfterInitialization()
方法,aop代理就是在此方法中完成的
12、将Bean放到单例池中(一级缓存)
13、获取工厂后调用getBean(“id”)调用的就是BeanFactory的doGetBean()方法
一级缓存
单例的Bean被创建后就被存放在一级缓存中,其实就是一个Map,只要这个单例bean被创建后,以后再次获取直接从Map中获取
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>
三级缓存
singletonFactories,三级缓存,主要存放半成品单例bean的被包装成的ObjectFactory,后续可以解决循环依赖,
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>
二级缓存
Map集合
private final Map<String, Object> earlySingletonObjects = new HashMap<>();
核心就是为了实现AOP
,如果注入的早期对象需要的是其代理对象,就需要使用三级缓存为早期对象生成代理,存到二级缓存中
去,最终返回早期实例是二级缓存中的其代理对象,使用三级缓存的本质在于解决AOP代理问题
第三级缓存存的是原生早期对象,第二级缓存中存的是经过代理之后的早期对象
就是不同类之间循环引用,比如A类的构造方法依赖B,B类的构造方法依赖A
1、原型循环依赖(
无法解决 只能抛出异常)
每次getBean都是创建新的对象,Spring不会去缓存对象,没有缓存池
2、单例构造方法循环依赖
(无法解决,只能抛出异常)
3、单例setter方法循环依赖
(可以解决,提前暴露对象(已完成实例化未完成初始化))
原型模式是当getBean(“id”)时Spring才会去根据BeanDefinition定义去反射创建对象,在创建对象时会将当前的beanName存到ThreadLocal中的一个Set集合中,当进行属性注入时发现依赖B,这时就会去获取B的对象,将B的beanName也存进ThreadLocal的Set中,然后B中也依赖A,这时就会去获取A,发现A的beanName已经存在于Set集合中,说明A 和B都处于正在创建的过程中,就可以说明发生了循环依赖,直接抛出异常
当根据A的BeanDefinition去创建对象时,在创建过程中会将beanName存到一个Set集合中,当进行属性注入时发现依赖B,这时就根据B的BeanDefinition创建B,这时B的beanName也会存进Set集合中,创建B的过程发现B依赖A,然后试图将A的beanName存到Set集合中,这时返现Set集合中已经有了A的beanName,即表示A正在创建中,就判断出了发生了循环依赖
singleton的Bean假设A在创建时会先将这个尚未经过属性注入和初始化的对象包装到一个ObjectFactory对象内,然后存到三级缓存中,key就是beanName,value就是ObjectFactory对象,然后在往下进行属性注入时发现依赖B,就去getBean()去获取B,单例池中没有B,就去根据B的BeanDefinition进而去创建B,在创建B的过程发现B依赖A,就去获取A,就去获取A暴露ObjectFactory对象,通过调用get方法
获取A的早期对象,进而完成对A的注入,然后B完成创建后,就将B的对象存到一级缓存中,然后回到A的逻辑完成B的注入
1、ApplicationContext是BeanFactory的子接口
2、 BeanFactory是工厂接口,负责创建Bean的实例,并保存这些单实例的bean在Map中
3、ApplicatonContext是容器的接口,比BeanFactory功能更加强大,更多的负责容器功能的实现,可以基于BeanFactory创建好的对象之上完成强大的容器,AOP DI都是ApplicatonContext接口下的这些类里,
BeanFactory是最底层的接口,ApplicatonContext是留给我们使用的ioc容器接口。
Spring最大的模式就是工厂模式