1. 创建Bean的过程(IOC底层原理)
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml")源码解读
this.setConfigLocations(configLocations);//把xml文件读取进来,读进来"bean1.xml"
this.refresh();
prepareRefresh();//前期准备工作
this.startupDate = System.currentTimeMillis();//设置启动时间
this.closed.set(false);//设置容器是关闭的
this.active.set(true);//设置容器是活跃的
//创建集合LinkedHashSet
//创建BeanFactory工厂
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.refreshBeanFactory();
//创建Bean工厂,下面的代码会创建好工厂
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());//设置序列化值
this.customizeBeanFactory(beanFactory);//自定义Bean工厂
this.loadBeanDefinitions(beanFactory);//加载bean定义信息
prepareBeanFactory(beanFactory);//给Bean工厂设置属性值
this.postProcessBeanFactory(beanFactory);//留给子类扩展使用
this.invokeBeanFactoryPostProcessors(beanFactory);//实例化并且调用所有已经注册的BeanFactoryProcessor
this.registerBeanPostProcessors(beanFactory);//实例化并注册BeanPostProcessors
this.initMessageSource();//完成国际化过程
this.initApplicationEventMulticaster();//初始化多播器(当事件发生之后,监听器要能给予不同的反应)
this.onRefresh();
this.registerListeners();//将监听器注册到多播器中
this.finishBeanFactoryInitialization(beanFactory);//对象实例化
beanFactory.preInstantiateSingletons();
//....
//默认采用无参构造器
//得到空的对象
populateBean(beanName,mbd,instanceWrapper)//填充属性,属性赋值
invokeAwareMethonds(beanName, bean);//给BeanFactory、BeanName、BeanClassLoader的属性设置值
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);//调用BeanPostProcessors的前置方法,设置applicationContext(Aware)
this.invokeInitMethods(beanName, wrappedBean, mbd);//调用初始化方法
//调用BeanPostProcessors的后置方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
this.finishRefresh();//完成扫尾工作
文字描述:IOC底层原理基于的是XML解析、工厂模式和反射共同实现的。
源码中,一开始会将xml文件读取出来,然后调用refresh方法完成具体的操作,进入refresh方法之后,首先会调用prepareRefresh方法完成前期准备,比如说设置启动时间、容器是关闭、或者活跃,以及创建集合的过程。然后调用obtainFreshBeanFactory方法创建BeanFactory,里面会加载bean定义信息,但得到的beanFactory很多是空的。接着要调用prepareBeanFactory方法给BeanFactory设置属性值。然后调用invokeBeanFacoryPostProcessors方法实例化并且调用所有已经注册的BeanFactoryProcessor。然后调用registerBeanPostProcesor实例化并注册BeanPostProcessors,但注意的是这里并没有真正执行BeanPostProcessor。接着调用finishBeanFactoryInitialization方法对对象进行实例化,默认会调用无参构造器,然后调用populateBean方法给属性赋值,之后就是依次调用BeanPostProcessors的前置方法,调用初始化方法和beanPostProcessor的后置方法。最后调用finishRefresh方法完成扫尾工作。
通俗的解释,首先会创建BeanFactory,BeanFactory的作用通过反射创建对象,然后将Bean的定义信息加载进IOC容器中,之后会调用BeanFactoryPostProcessor方法,然后就是BeanFactory使用反射创建Bean,然后调用populateBean方法给属性赋值,之后就是依次调用BeanPostProcessors的前置方法,调用初始化方法和beanPostProcessor的后置方法,此时就能获取到能用的Bean实例了。
IOC容器:从对象的创建到对象的使用再到对象的销毁全部由容器来帮我们控制,用户只需要使用即可。
IOC容器里存储的是map结构
如何告诉Spring所需要管理的对象:XML、注解@Bean...
从配置文件到对象的大致过程:
使用方式:获取ApplicationContext对象,调用applicationContext.getBean方法
XML、注解等地方定义的Bean要转换成BeanDefinition的方法如下:
BeanFactory:是访问Spring Bean容器的根接口
PlaceholderConfiguerSupport用于处理占位符的替换,例如:${}
Spring的自动装配:ConfigurationClassPostProcessor中可以解析Component注解、接卸@PropertySource注解、@ComponentScan注解等。
创建对象分为:实例化、初始化
Bean生命周期:
调用Aware接口的方法:为了个BeanFactory和ApplicationContext赋值
beanPostProcessor方法是为了对Bean进行扩展,完成额外功能,例如aop,实现子类里有关于动态代理的。
容器和对象的创建流程:
Refresh方法
XML如何进行解析的:
首先xml会根据encodedResource.getResource().getInputStream()获取IO流,其次,使用doLoadDocument方法将IO流转化为document, 解析时会把子元素根据是不是默认命名空间分成2类,如果是默认命名空间,则调用parseDefaultElement方法,如果不是则调用parseCustomElement方法,找到对应的处理器handler对不同的元素进行解析工作。
循环依赖:
问题阐述:
解决循环依赖的本质:实例化和初始化分开
创建对象的核心方法名称:
循环依赖的产生原因:
解决方法:
三级缓存:
查找容器中是否有bean对象
循环依赖解决方案原理:
文字描述:
进入preInstantiateSingletons()方法依次创建对象,每次创建对象时会进入getSingleton方法去查看一级缓存有没有,如果一级缓存有就不会在创建了。如果首次创建,缓存里肯定没有就会依次调getBean()、doGetBean()方法,依然会先getSingleton(beanName)看下缓存中有没有,如果没有,则会进入getSingleton(beanName,createBean()(lambda表达式),进入之后,首先也会看一级缓存中有没有,没有就调用singletonFactory.getObject()方法,也就是createBean()方法,之后再进入doCreateBean()方法,调用createBeanInstance()方法创建A对象,此时A对象中b=null,再调用addSingletonFactory(beanName, getEarlyBeanReference)方法,此时三级缓存里面就有key:A的数据了,然后再调用populateBean方法填充属性b,进入populateBean方法后,调用applyPropertyValues去设置属性值,最后会调用beanFactory.getBean获取b的对象,流程和之前一样,最后调用createBeanInstance()方法创建B对象,此时B对象中的A为空,再调用addSingletonFactory(beanName, getEarlyBeanReference)方法,此时三级缓存里面就有key:B的数据了,然后再调用populateBean方法填充属性a,进入populateBean方法后,调用applyPropertyValues去设置属性值,最后会调用beanFactory.getBean获取a的对象,调用doGetBean()方法,调用getSingleton方法会获得a对象,并且把a对象(半成品)放入二级缓存中,并把三级缓存中的key:a删了。 然后再调用setPropertyValues给b中的a属性赋值。之后b对象就创建完成了。 b对象创建完成之后在getSingleton(beanName,createBean()的最后,会调用addSingleton()方法,将b对象(成品)放入一级缓存,并删除二级,三级缓存中的数据。现在就需要调用setPropertyValues给a中的b属性赋值.此时a对象创建完成,然后调用addSingleton()方法。至此a对象创建完成。之后就要创建b对象了,但是b对象之前已经创建完成了。
注:getSingleton方法:如果一级缓存有,就返回对象,如果一级缓存没有,就看二级缓存有没有,如果二级缓存有,就返回对象,如果二级没有,就看三级有没有,三级如果有就调用getObject()方法(也就是调用getEarlyBeanReference方法)获得对象,并把对象放入二级缓存中,并删除三级缓存中的。
addSingletonFactory方法:如果一级缓存没有,就把getEarlyBeanReference这个lambda表达式放入三级缓存,并移除二级缓存中的对象
如果只用二级缓存能解决循环依赖吗?可以