zoukankan      html  css  js  c++  java
  • spring 初始化Bean

    说起spring bean的初始化自然而然就离不开初始化阶段的循环引用;
    1 首先spring容器在启动后会创建一个beanFactory,new DefaultListableBeanFactory。

    2 然后在spring容器启动过程中会调用核心的refresh方法,在这个方法中共调用了9个方法,即为spring容器的初始过程,所以说spring容器不单单是我们狭义概念中的map那么简单,在这个方法中包含两个最最主要的方法:

    2.1 invokeBeanFactoryPostProcessors(beanFactory)
          在这个方法中,会调用spring的beanFactory后置处理器,将所有扫描到要注册为Bean的javaClass信息收集后,构建成BeanDefinition,后register到beanDefinitionMap中,为以后Bean的初始化提供信息。

    2.2 finishBeanFactoryInitialization(beanFactory)
          该方法显得更加额外的重要,在这个方法的最后阶段会调用preInstantiateSingletons,很明显在这个方法中我们要初始化Scope为single的bean,而原型bean则不需要单独做处理, 因为原型bean无论是初始化阶段还是注入阶段都是直接创建“对象或者代理对象”
         preInstantiateSingletons方法中调用了getBean方法,之后使用了委托模式调用了doGetBean方法。doGetBean方法中调用了两次getSingleton方法,并且经过了3个缓存Map(singleObjectMap,singletonFactory,earlySingleObjects),两次调用的本质就是解决循环引用的问题;因为如果不存在循环引用的话就会直接调用creatBean方法去走bean的创建流程了。

          话又说回来,第一次调用getSingleton的时候直接指定了循环引用为true,进入第二个getSingleton方法;
           (1)会先从bean的缓存池中获取创建好的bean对象,但是一定是获取失败的,因为bean没有走完生命周期的创建过程。
           (2)会在从earlySingletonObject缓存Map中去拿,因为首次创建刚刚进行,该Bean还没有被标记为“创建状态”所以仍然无法获取。
           (3)两次获取失败后,就会调用第三种getSingleton方法,通过lambda表达式中的createBean方法去走实际创建对象的过程了,在执行createBean之前有个重要的环节就是当 前的初始状态Bean已经被加入到“创建状态的集合中”,并且已经将创建bean的工厂放入了singletonFactoriesMap缓存集合中。

     public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
            Assert.notNull(beanName, "'beanName' must not be null");
            Map var3 = this.singletonObjects;
            synchronized(this.singletonObjects) {
                Object singletonObject = this.singletonObjects.get(beanName);
                if(singletonObject == null) {
                    if(this.singletonsCurrentlyInDestruction) {
                        throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                    }
    
                    if(this.logger.isDebugEnabled()) {
                        this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                    }
    
                    this.beforeSingletonCreation(beanName);
                    boolean newSingleton = false;
    protected void beforeSingletonCreation(String beanName) {
    if(!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
    }
    }

    3 在createBean方法中仍然通过委托模式继续调用doCreateBean方法,doCreateBean方法中也有2了核心方法:

    3.1 createInstance会创建出一个java类本身的wapper对象;

    if(instanceWrapper == null) {
    instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    3.2 populateBean方法会将包装对象中带有Bean注解的成员变量进行注入
          在这个方法中会去装配autowire注解的对象,这个时候会继续调用getBean方法,然后再次调用getSingleton方法,执行之前的一系列重复createBean操作。
          那么此时应该注意,循环依赖发生后,注入属性对象仍然会持有原来对象,但是原来对象在调用第二次getSingleton方法时,已经可以通过二级缓存中的singleFactoryMap获取到Factory,并实例化Bean放入到earlySingleObjectMap三级缓存中,从而获取到对象。这样循环依赖就不会造成死循环循环创建了。(这里二级缓存工厂,作用就是可能返回原对象或发生AOP之后的增强代理对象,实质是由Bean的后置处理器执行后的结果)

    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
            PropertyValues pvs = mbd.getPropertyValues();
            if(bw == null) {
                if(!((PropertyValues)pvs).isEmpty()) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
                }
            } else {
                boolean continueWithPropertyPopulation = true;
                if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                    Iterator var6 = this.getBeanPostProcessors().iterator();
    
                    while(var6.hasNext()) {
                        BeanPostProcessor bp = (BeanPostProcessor)var6.next();
                        if(bp instanceof InstantiationAwareBeanPostProcessor) {
                            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                            if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                                continueWithPropertyPopulation = false;
                                break;
                            }
                        }
                    }
                }
    
                if(continueWithPropertyPopulation) {
                    if(mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                        MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                        if(mbd.getResolvedAutowireMode() == 1) {
                            this.autowireByName(beanName, mbd, bw, newPvs);
                        }
    
                        if(mbd.getResolvedAutowireMode() == 2) {
                            this.autowireByType(beanName, mbd, bw, newPvs);
                        }
    
                        pvs = newPvs;
                    }
    
                    boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
                    boolean needsDepCheck = mbd.getDependencyCheck() != 0;
                    if(hasInstAwareBpps || needsDepCheck) {
                        PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        if(hasInstAwareBpps) {
                            Iterator var9 = this.getBeanPostProcessors().iterator();
    
                            while(var9.hasNext()) {
                                BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                                if(bp instanceof InstantiationAwareBeanPostProcessor) {
                                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                                    pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                                    if(pvs == null) {
                                        return;
                                    }
                                }
                            }
                        }
    
                        if(needsDepCheck) {
                            this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
                        }
                    }
    
                    this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
                }
            }
        }
    View Code

    3.3 属性装配结束后调用initializeBean方法就是去调用Bean实现的接口回调函数,也就是一系列的Bean后置处理器方法。

     protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
            if(System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
                        return null;
                    }
                }, this.getAccessControlContext());
            } else {
                this.invokeAwareMethods(beanName, bean);
            }
    
            Object wrappedBean = bean;
            if(mbd == null || !mbd.isSynthetic()) {
                wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
            }
    
            try {
                this.invokeInitMethods(beanName, wrappedBean, mbd);
            } catch (Throwable var6) {
                throw new BeanCreationException(mbd != null?mbd.getResourceDescription():null, beanName, "Invocation of init method failed", var6);
            }
    
            if(mbd == null || !mbd.isSynthetic()) {
                wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
    
            return wrappedBean;
        }
    View Code
  • 相关阅读:
    开源项目之Android StandOut(浮动窗口)
    小智慧7
    安卓学习
    asp.net学习Request和Response的其他属性
    bash中的转义
    POJ 1833 排列
    Django点滴(四)ORM对象存取
    POJ 1681 Painter's Problem
    linux2.6.32在mini2440开发板上移植(21)之WebServer服务器移植
    [gkk传智]static与多态及向下向上转型,及多态调用总结
  • 原文地址:https://www.cnblogs.com/zzq-include/p/11988310.html
Copyright © 2011-2022 走看看