Spring源码笔记(四)Bean加载

Bean的加载

当解析完Bean的配置文件后,就要开始获取Bean,获取Bean则需要先加载,接下来就解析加载的过程;

People p =(People) bf.getBean("people");

1. getBean(String name)

public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

当我们跳转到还有该方法的类时,发现有很多类都有该方法,判断则是,根据具体具体的名字做分析;这里跳转的类为AbstractBeanFactory的getBean

2.doGetBean(...)

doGetBean的方法有150多行代码,大致执行的流程如下:

  1. 获取BeanName;

  2. 在缓存中寻找Bean是否以前加载过;

  3. 如果没有在缓存中,则去工厂中寻找Bean;

    3.1进行类型检查或者创建对象;

    3.2递归实例化依赖的bean;

    3.3根据不同的scope创建不同的对象;

    3.4检查需要的类型是否符合bean的实际类型;

3.transformedBeanName(name);

实际执行的代码为:

String FACTORY_BEAN_PREFIX = "&";
public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");
        String beanName = name;
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        return beanName;
    }

该方法的作用是:过滤掉factory的修饰符&,得到具体的beanName;

4.getSingleton(beanName);

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }}}}
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

首先是从singletonObjects中获取对象,如果没有,则从earlySingletonObjects中获取对象,如果还没有,则从工厂中获取对象,然后将获取的对象放入到earlySingletonObjects缓存中,以方便下次直接从earlySingletonObjects中获取,然后将对象从singletonFactories中删除,然后返回Object对象;

5.getObjectForBeanInstance(sharedInstance, name, beanName, null);

protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
        if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }
​
        Object object = null;
        if (mbd == null) {
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

该方法所做的工作有:

对指定的name的工厂进行判断;

根据name来决定是否需要返回工厂实例而不是工厂的getObject方法;

尝试从缓存中加载bean;

将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition;

6.getObjectFromFactoryBean(factory, beanName, !synthetic)

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;}
                    else {
                        if (object != null && shouldPostProcess) {
                            try {
                                object = postProcessObjectFromFactoryBean(object, beanName);}
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);}}
                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));}}
                return (object != NULL_OBJECT ? object : null);}}
        else {
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (object != null && shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);}
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }}
            return object;}}

该方法的作用有:

判断Bean是否是单例模式,如果是,则从缓存中加载对象,如果缓存中没有,则使用doGetObjectFromFactoryBean(factory, beanName);并将bean对象放入到缓存中,如果不是,则使用doGetObjectFromFactoryBean(factory, beanName);

7.doGetObjectFromFactoryBean(factory, beanName)

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
            throws BeanCreationException {
        Object object;
        try {
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                                return factory.getObject();}
                        }, acc);}
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }}
            else {
                object = factory.getObject();}}
        catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }
        if (object == null && isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(
                    bef5ddsanName, "FactoryBean which is currently in creation returned null from getObject");
        }
        return object;
    }

8.doGetBean

当Bean没有在缓存中时,接下来执行有:

isPrototypeCurrentlyInCreation(beanName)

该代码时将beanName进行标记,用来判断依赖循环。

BeanFactory parentBeanFactory = getParentBeanFactory();

从parentBeanFactory中检查Bean;

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

将GenericBeanDefinition转换为RootBeanDefinition;如果是子类bean,则同时合并父类的相关属性;

String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        getBean(dep);
                    }
                }

递归遍历需要实例化的依赖;

if (mbd.isSingleton()) {
......
    return createBean(beanName, mbd, args);
......  

根据配置文件中的scope的设置,开始具体的创建过程;

createBean(beanName, mbd, args);

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }
        try {
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }

根据Bean名解析BeanClass;

对Override属性进行标记以及验证;

应用初始化前的后处理器,解析bean初始化前的短路操作;

创建bean;

mbdToUse.prepareMethodOverrides();

prepareMethodOverride(mo);
==》
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    ......
    }

spring配置中没有override-method配置,spring配置中存在lookup-method和replace-method,而这两个配置的加载其实是统一存放在BeanDfinition中的methodOverrides属性里。这个属性就是操作这两个配置;

resolveBeforeInstantiation(beanName, mbdToUse);

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;}

主要有两个方法,即实例化前的后处理器applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);实例化后的后处理器applyBeanPostProcessorsAfterInitialization(bean, beanName);

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);}
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        mbd.resolvedTargetType = beanType;
        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);}
                mbd.postProcessed = true;
            }}
​
        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");}
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });}
​
        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }}
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;}
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }}
​
        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;}
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }}
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }}}}
        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }
​
        return exposedObject;
    }
​

该方法比较复杂,我们分段介绍重要的:

如果是单例,则清除缓存,

if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}

实例化Bean,将BeanDefinition转化为BeanWrapper;

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

createBeanInstance(beanName,mbd,args)

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        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());
        }
        if (mbd.getFactoryMethodName() != null)  {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }
        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);
            }
        }
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }
        return instantiateBean(beanName, mbd);
    }

该方法首先是解析class;

接下来判断类和方法的权限修饰;类必须是pulic,函数必须是public,注意这里已经不是单例;

如果工厂方法不为null,则使用工厂方法初始化策略;

如果工厂方法为空,则使用构造函数进行类的实例化;

当一个函数有多个构造函数时,这里需要同步确认使用的构造函数;

如果已经解析过则使用解析好的构造函数方法,接下来判断是否需要自动注入,需要的话则开始构造函数自动注入,不需要的话,则使用默认构造函数构造;(因为每次都根据参数及类型去判断使用哪个构造函数进行实例化,比较消耗性能,则使用缓存机制);

接下来根据参数解析构造函数,如果参数不为空,且有自动注入标识等,则使用构造函数自动注入,否则使用默认构造函数构造;

autowireConstructor(beanName, mbd, null, null);

调用内部的autowireConstructor(beanName, mbd, ctors, explicitArgs);

由于该方法比较长,则还是分块介绍重点:

该方法首先创建创建几个有关构造器,参数的变量;

接下来判断getBean方法在调用的时候,有没有显示的指定方法的参数,如果有,则直接使用,如果没有,从配置文件中解析,接下来锁定特定的构造器,然后从缓存中提取对象;如果缓存中存在,则进行参数转换,将参数转换为最终需要的,如果缓存中不存在,则接下来通过RootBeanDefinition对象中解析构造函数信息,解析构造函数中参数的值;

接下来给构造函数排序,遍历构造函数,判断参数,如果参数不为空,找到对应参数的构造函数,然后根据值构造对应参数类型的参数,获取参数名称探索器,获取指定构造函数的参数名称;根据名称和数据类型创建参数持有者;如果参数为空,则使用无参的构造函数;

接下来判断是否有不确定性的构造函数存在;如果有,并且代表最接近的匹配则选择作为构造函数;

然后将解析的构造函数加入缓存;

将构建的实例加入BeanWrapper中;

instantiateBean(beanName, mbd);

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            final BeanFactory parent = this;
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                    }
                }, getAccessControlContext());
            }
            else {
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
            }
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }

该方法即使用默认构造器实例化一个bean,主要是beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);该方法,

instantiate(mbd, beanName, parent)

public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
        if (bd.getMethodOverrides().isEmpty()) {
.....
                        if (System.getSecurityManager() != null) {
                            constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                                @Override
                                public Constructor<?> run() throws Exception {
                                    return clazz.getDeclaredConstructor((Class[]) null);
                                }});}
                        else {
                            constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);}
                        bd.resolvedConstructorOrFactoryMethod = constructorToUse;}
                    ......
            return BeanUtils.instantiateClass(constructorToUse);}
        else {
            // Must generate CGLIB subclass.
            return instantiateWithMethodInjection(bd, beanName, owner);
        }
    }

该方法首先判断(bd.getMethodOverrides().isEmpty(),即用户有没有使用replace或者lookup的配置方法,如果没有则直接使用反射的方式,如果使用了这两个特性,则需要使用CGLIB将这个特性对应的逻辑织入进去。

populateBean(beanName, mbd, instanceWrapper);

doCreateBean类下;
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
......
​
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
​
            // Add property values based on autowire by name if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
​
            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
......
​
    }

该方法主要有:

属性填充的判断;

根据注入类型(autowireByName|autowireByType),提取依赖的bean;

对属性获取完毕填充前对属性的再次处理;

将所有PropertyValues中的属性填充到BeanWrapper中;

 

《参考Spring源码深度解析》

如有问题,敬请指出,与君共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值