美文网首页
spring(三)bean的加载

spring(三)bean的加载

作者: chengcongyue | 来源:发表于2019-04-09 09:30 被阅读0次

    入门

    @Override
        public Object getBean(String name, Object... args) throws BeansException {
            return doGetBean(name, null, args, false);
        }
    doGetBean的大概功能如下:
    1,提取对应的BeanName
    2,检查缓存或者实例工厂的是否有对应的实例
    创建bean的时候会有依赖注入的情况,这种情况下为了避免循环依赖,Spring加载的原则是不能bean加载完成,就将bean对应的ObjectFactory放入到缓存中
    (提前曝光)
    直接尝试从ObjectFactory中获取
    3,返回定义的实例,有时候并不是返回实例本身,而是返回指定方法的返回的实例
    4,如果已经加载的类不包括BeanName,尝试从父工厂中检测
    ......
    

    下面是详细介绍
    1.转换beanName
    2.尝试从缓存中加载单例
    3.bean的实例化
    4.原型模式的依赖检查
    5.检测parentBeanFactory
    ...

    1 FactoryBean的使用

    Spring通过反射机制利用bean的class属性来实例化bean,Spring中提供了工厂类的接口,借此来实现实例化bean的逻辑

    public interface FactoryBean<T> {
    T getObject() throws Exception;
    Class<?> getObjectType();
    default boolean isSingleton() {
            return true;
        }
    }
    
    摘自书籍
    如果bean的实现类是FactoryBean时,通过getBean返回的并不是FactoryBean本身而是getObject()的方法所返回的对象,相当于是getObject()代理了getBean()方法

    2 缓存中获取单例的bean

    bean的加载,一个bean实例只会被创建一次,第二次获取直接从缓存中获取,如果没有再次从SingletonFactory中获取.
    在单例模式下存在的循环依赖问题,解决的方法是:
    不等bean加载完成就将bean的ObjectBean放入到缓存中,下次需要使用到这个bean时,直接使用它的ObjectFactory

    图片
    摘自书籍

    3,从bean的实例中获取对象

    从缓存中获取到的bean和通过不同的scope中获取到的bean不是最后要使用的bean,我们需要的bean是Factory-method的返回的bean
    在使用FactoryBean时,返回的对象时getObject()创建的bean,核心语句为

    object = factory.getObject();
    

    4 获取单例

        public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
            Assert.notNull(beanName, "Bean name must not be null");
            synchronized (this.singletonObjects) {
                Object singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    if (this.singletonsCurrentlyInDestruction) {
                         ....
                    beforeSingletonCreation(beanName);
                     .....
                    }
                    try {
                        singletonObject = singletonFactory.getObject();
                        newSingleton = true;
                    }
                    ......
                        afterSingletonCreation(beanName);
                    }
                    if (newSingleton) {
                        addSingleton(beanName, singletonObject);
                    }
                }
                return singletonObject;
            }
        }
    

    beforeSingletonCreation(beanName);
    singletonObject = singletonFactory.getObject();(核心语言)
    afterSingletonCreation(beanName);

    5 准备创建bean

        protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            
            try {
                mbdToUse.prepareMethodOverrides();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                        beanName, "Validation of method overrides failed", ex);
            }
    
            try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                if (bean != null) {
                    return bean;
                
            }
        }
    

    prepareMethodOverrides方法如下

        public void prepareMethodOverrides() throws BeanDefinitionValidationException {
            // Check that lookup methods exists.
            if (hasMethodOverrides()) {
                Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
                synchronized (overrides) {
                    for (MethodOverride mo : overrides) {
                        prepareMethodOverride(mo);
                    }
                }
            }
        }
    
    protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
            int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
            if (count == 0) {
                throw new BeanDefinitionValidationException(
                        "Invalid method override: no method with name '" + mo.getMethodName() +
                        "' on class [" + getBeanClassName() + "]");
            }
            else if (count == 1) {
                // Mark override as not overloaded, to avoid the overhead of arg type checking.
                mo.setOverloaded(false);
            }
        }
    

    相当于是面向切面,当有methodOverWritten,就会为bean创建一个增强

    5.2 实例前的处理

    try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                if (bean != null) {
                    return bean;
                }
            }
    

    我们进入resolveBeforeInstantiation进行查看

    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
            Object bean = null;
            if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
                // Make sure bean class is actually resolved at this point.
                if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                    Class<?> targetType = determineTargetType(beanName, mbd);
                    if (targetType != null) {
                        bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                        if (bean != null) {
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                        }
                    }
                }
                mbd.beforeInstantiationResolved = (bean != null);
            }
            return bean;
        }
    

    在我们创建bean之前,会进行applyBeanPostProcessorsBeforeInstantiation,applyBeanPostProcessorsAfterInitialization的处理

    6.常规的bean的创建

    6.1我们对doCreateBean进行分析

    instanceWrapper = createBeanInstance(beanName, mbd, args);
    

    (1)如果是单例,先清除缓存
    (2)实例化bean,将beanDefinition转换为BeanWrapper
    (3)applyMergedBeanDefinitionPostProcessors
    (4)依赖的处理

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                    isSingletonCurrentlyInCreation(beanName));
            if (earlySingletonExposure) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Eagerly caching bean '" + beanName +
                            "' to allow for resolving potential circular references");
                }
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    

    (5)填充属性
    (6)..
    (7)..

    6.2创建bean的实例

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
            // Make sure bean class is actually resolved at this point.
            Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
            if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
            }
    
            Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
            if (instanceSupplier != null) {
                return obtainFromSupplier(instanceSupplier, beanName);
            }
    
            if (mbd.getFactoryMethodName() != null) {
                return instantiateUsingFactoryMethod(beanName, mbd, args);
            }
    
            // Shortcut when re-creating the same bean...
            boolean resolved = false;
            boolean autowireNecessary = false;
            if (args == null) {
                synchronized (mbd.constructorArgumentLock) {
                    if (mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }
            if (resolved) {
                if (autowireNecessary) {
                    return autowireConstructor(beanName, mbd, null, null);
                }
                else {
                    return instantiateBean(beanName, mbd);
                }
            }
    
            // Candidate constructors for autowiring?
            Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
            if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
                return autowireConstructor(beanName, mbd, ctors, args);
            }
    
            // Preferred constructors for default construction?
            ctors = mbd.getPreferredConstructors();
            if (ctors != null) {
                return autowireConstructor(beanName, mbd, ctors, null);
            }
    
            // No special handling: simply use no-arg constructor.
            return instantiateBean(beanName, mbd);
        }
    

    以上代码的意思如下:摘自书籍
    (1),解析class
    (2),如果工厂方法不为空,那么通过工厂方法
    (3),对于不同的构造函数,要指定它的参数
    (4),.......

    if (mbd.getFactoryMethodName() != null) {
                return instantiateUsingFactoryMethod(beanName, mbd, args);
            }
    

    6.2.1 autowireConstructor

    代码量过多,直接分析功能
    (1)构造函数参数的确定
    从如下代码中获取,如果explicitArgs 不是空,那么构造函数的参数就是它

    if (explicitArgs != null) {
                argsToUse = explicitArgs;
            }
    

    构造函数的参数可能在缓存中,这样可以从缓存中获取
    如果以上两种方式都不可能,则执行如下的代码

    ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
    

    (2)构造函数的确定
    根据(1)构造函数的参数来确定构造函数
    (3)转化构造类型
    (4)构造函数不确定的验证
    (5)根据实例化策略以及得到的构造函数以及构造函数参数实例化bean

    6.2.2 无参构造

    6.2.3 实例化策略

    用户如果没有使用replace和lookUp的配置方法,那么直接使用反射的方式,简单快捷,如果有的话,那就需要使用动态代理的方式将增强设置进去

    6.3 记录创建bean 的ObjectFactory

    我们来看如下代码

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                    isSingletonCurrentlyInCreation(beanName));
    

    是否是单例
    是否是循环依赖
    是否已经在创建中
    当以上三个条件都满足时,我们执行如下的代码

    if (earlySingletonExposure) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Eagerly caching bean '" + beanName +
                            "' to allow for resolving potential circular references");
                }
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    

    我们重点看一下addSingletonFactory这个方法

        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    

    其中调用了getEarlyBeanReference这个方法,我们在进入这个方法一探究竟
    我们关注的是B在填充属性时,不是递归调用,而是使用getBean方法,其意思是指直接调用ObjectFactory来创建A,但B持有的A是没有任何属性的A

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
            Object exposedObject = bean;
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                        exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                    }
                }
            }
            return exposedObject;
        }
    
    解决循环依赖

    6.4 属性注入

    我们来看第一个方法autoWireByName,具体功能就是通过value找到已经加载的bean,并递归实例化,然后在放入其中,然后在来看autoWireByType,查看需要注入的属性,遍历这些属性找到与其相配的bean
    这时候就获取到了所有的注入属性

    if (pvs != null) {
                applyPropertyValues(beanName, mbd, bw, pvs);
            }
    通过这个方法,就可以将属性应用到bean中
    

    6.5 初始化bean

    执行初始化之前,已经完成了属性的填充,以及实例化

    相关文章

      网友评论

          本文标题:spring(三)bean的加载

          本文链接:https://www.haomeiwen.com/subject/glsviqtx.html