IOC容器就像是一个工厂,里面有很多流水线生产出一个个产品(bean)。bean的加载流程大概分为:
- 容器启动阶段
- bean加载阶段
1.配置元信息
当你生产物品的时候总得知道产品得规格型号信息,元信息就是这个意思。来源于XML文件,注解等。
2.BeanDefination:
相当于java中得pojo,当元信息被加载到内存以后就是以BeanDefination的形式存在。
3、BeanDefinationReader:如果我们要读取xml配置元信息,那么可以使用XmlBeanDefinationReader。如果我们要读取properties配置文件,那么可以使用PropertiesBeanDefinitionReader加载。而如果我们要读取注解配置元信息,那么可以使用 AnnotatedBeanDefinitionReader加载。我们也可以很方便的自定义BeanDefinationReader来自己控制配置元信息的加载。总的来说,BeanDefinationReader的作用就是加载配置元信息,并将其转化为内存形式的BeanDefination,并存在BeanDefinationRegistry中。通过键值对的方式,键是通过特定的bean定义的id,映射到相应的BeanDefination。
4、BeanDefinationRegistry:
执行到这里,Spring已经将存在于各处的配置元信息加载到内存,并转化为BeanDefination的形式,这样我们需要创建某一个对象实例的时候,找到相应的BeanDefination然后创建对象即可。那么我们需要某一个对象的时候,去哪里找到对应的BeanDefination呢?这种通过Bean定义的id找到对象的BeanDefination的对应关系或者说映射关系又是如何保存的呢?这就引出了BeanDefinationRegistry了。
Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。
5、BeanFactoryPostProcessor:
BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。例如我们的配置元信息中有些可能会修改的配置信息散落到各处,不够灵活,修改相应配置的时候比较麻烦,这时我们可以使用占位符的方式来配置。例如配置Jdbc的DataSource连接的时候可以这样配置:
BeanFactoryPostProcessor就会对注册到BeanDefinationRegistry中的BeanDefination做最后的修改,替换$占位符为配置文件中的真实的数据。
二、Bean的获取阶段
在容器的启动阶段就完成了bean的注册,以BeanDefination储存在BeanDefinationRegister中,如果不是选择懒加载(BeanFactory是懒加载)的话,在容器启动完成后执行finishBeanFactoryInitialization()方法,隐式的调用所有对象的getBean()方法实例化所有配置的Bean,完成类的加载。
1.doGetBean():bean的获取
doGetBean的方法就是创建Bean之前,先去缓存中或BeanFactory工厂中查看是否存在bean,如果存在,则返回,不存在则进行相应的创建流程。
- 检查是不是别名,需要进行解析转换
- 尝试从缓存中加载实例,如果获取直接返回,在缓存中获取的bean是原始bean还需要进行实例化,如合并RootBeandefination、BeanPostProcessor进行实例前置处理,实例化,实例后置处理。
- 如果缓存中没有对应的bean,则先进行依赖循环检查,存在则报错,如果缓存中没有数据,就会转到父类加工厂(有点像双亲委任制),如果当前的xml文件不报换beanname所对应的配置,就只能到父类工厂中尝试加载
- 存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。
- 初始化依赖的bean,即进行被依赖bean的实例化初始化流程。
- 创建bean,默认是单例
protectedT doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; //2、尝试从缓存中去加载实例,如果获取到了就直接返回 // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); //如果缓存中存在对应的bean if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } //3、缓存渠道的bean的实例化。从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化。 // 此时会进行 合并RootBeanDefinition、BeanPostProcessor进行实例前置处理、实例化、实例后置处理。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } // 如果缓存中没有对应bean else { //4、循环依赖检查。 (构造器的循环依赖)循环依赖存在,则报错。 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 5、如果缓存中没有数据,就会转到父类工厂去加载 //获取父工厂 // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); //!containsBeanDefinition(beanName)就是检测如果当前加载的xml配置文件中不包含beanName所对应的配置,就只能到parentBeanFacotory去尝试加载bean。 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } //6、存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。 try { // XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但Bean的后续处理是针对于RootBeanDefinition的,所以需要转换后才能进行后续操作。 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. //7、初始化依赖的bean String[] dependsOn = mbd.getDependsOn(); //bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。 if (dependsOn != null) { for (String dependsOnBean : dependsOn) { if (isDependent(beanName, dependsOnBean)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'"); } registerDependentBean(dependsOnBean, beanName); getBean(dependsOnBean); } } //8、创建bean // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory
2.在缓存中获取单例bean 调用getSingleton(beanname,allowearlyReference)方法
1).从一级缓存中获取,若为空,则检查是否在创建中
2).检查的时候要加锁,防止并发创建
3).从二级bean中获取bean,如果正在加载,则不处理,否则调用addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories,也就是三级缓存中,三级缓存存储的也是早期bean。在解决循环依赖中,三级缓存是可以对早期的类对象进行自定义处理,将处理完的对象,放在二级缓存中,若还有循环依赖的处理,拿的是二级循环中的对象。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从缓存池中获取bean:singletonObjects 一级缓
Object singletonObject = this.singletonObjects.get(beanName);
// 如果一级缓存中为null,再判断是否正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加锁,防止并发创建
synchronized (this.singletonObjects) {
// 从二级缓存中获取bean,如果此 bean 正在加载则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 当某些方法需要提前初始化,调用 addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
Bean实例化阶段执行的顺序



