spring的加载bean:
1.创建applicationcontext容器,调用其构造方法,在这个构造方法,首先创建bean工厂,这个beanFactory是一个接口,没有具体的实现,里面最常用的就是DefaultListableBeanFactory,设置一些参数。
2.扫描class:
在你创建AnonationApplicationContext创建一个容器,根据传过来的class对象,扫描上面指定的包路径,扫描该路径及下
的所有class文件利用包+类名,反射出class对象 Class.forName("xxx.xxx")
2.bean的注册:
Spring会检查每个扫描到的class对象,判断是否带有特定的注解(如@Component、@Service等)如果类带有特定的注解,
Spring会解析该注解,并获取其中的信息,如Bean的名称、依赖关系等放到beanDefinition中,保存到beanDefinitionMap中
3.实例化初始bean:
扫描完后,对这个map进行循环,通过每个beanDefinition中的class信息,是否是预加载,是否是单例,是就把key做beanName,通过class对象
创建实例对象:
工厂方法:注解@Bean FatoryBean:实现FactoryBean接口 反射:获取class,获取构造器,推断构造方法,创建实例对象
4.属性填充:
(循环依赖的解决:三级缓存:singletonFactories、earlySingletonObjects、singletonObjects三个map)
实例化初始bean1后,那么这个bean1就处于正在初始化中,将其添加到singletonFactories中,key为beanName,对象做值,接下来开始填充属性
如果属性上有DI注解,如@Autowried,就先看这个对象是否是一个已经注册的bean,就是在beanDefinitionMap中根据类型找,没有就报错,有多个,再根据name找,找到说明这是个bean,根据beanDefinition是否单例,是从singletonObjects找,没找到,就创建这个bean2,进入这个bean2的生命周期,继续实例化初始bean2后,那么这个bean2就处于也正在初始化中,将其添加到singletonFactories中,开始填充bean2的属性,因为bean2也依赖bean1,bean1目前正在初始化中,所以singletonObjects找不到,于是从singletonFactories找,找到后从singletonFactories移除,并添加到earlySingletonObjects中,完成属性的填充,完成了初始化,添加到singletonObjects中,于是继续进入到了bean1的bean2注入中,因为bean2完成了初始化,可以在singletonObjects找到,于是也就完成了bean1的属性填充。(,如果期间还有其他对象依赖了bean1,又因为bean1的因为singletonFactories移除过,其他的对象依赖会从earlySingletonObjects取,这样earlySingletonObjects就保证了所有依赖我的bean1中的对象是同一个对象,保证单例),这个bean
完成加载,那么我正在创建的bean1也可以完成bean的注入及其他属性的填充
5.bean初始化:
属性填充完,spring在这里提供了许多Aware回调方法,具体就是实现BeanNameAware或其他接口,实现其中的方法,Spring会在这里帮你去调用这个方法,完成
容器基础属性的赋值
使用@PostStruct,spring会在这调用,实现InitingnaizeBean接口,Spring调用AfterPropertiesSet方法
BeanPostProccessor,Spring的后置处理器,这个接口有两个方法,在初始化后在这个方法完成aop的代理
aop代理:
cglib jdk
重写被代理类 实现被代理类接口
得到代理对象: Proxy.newProxyNewInstance(proxy,method,getInterfaces()){//切面逻辑}
//切面逻辑
super.xxx()
//切面逻辑
6.将这个bean添加到singletonObjects中,即单例池,remove其他两个map中的值,即完成了这个bean的加载
7.循环这个步骤加载所有bean