Spring源码分析(二)-Spring IoC容器的初始化No.2

Spring源码分析(一)-Spring IoC容器的初始化No.1中已经分析了Bean的加载过程,本章将分析Bean的实例化过程

本章围绕refresh().finishBeanFactoryInitialization(beanFactory)方法,聊聊Spring是如何实例化bean的,(一)中已经附上refresh的代码,从代码片段中的注解不难看出,此方法主要的任务就是实例化非懒加载的单例bean,看代码

    /** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        beanFactory.freezeConfiguration();

        // Instantiate all remaining (non-lazy-init) singletons.
        beanFactory.preInstantiateSingletons();
    }

非常清晰地从注释中获得信息,最后一个方法实例化所有单例Bean,看一下beanFactory.preInstantiateSingletons()的代码

    @Override
    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        List<String> beanNames;
        synchronized (this.beanDefinitionMap) {
            // Iterate over a copy to allow for init methods which in turn register new bean definitions.
            // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
            beanNames = new ArrayList<String>(this.beanDefinitionNames);
        }

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            @Override
                            public Boolean run() {
                                return ((SmartFactoryBean<?>) factory).isEagerInit();
                            }
                        }, getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }
    }

此方法首先将加载进来的beanDefinitionNames循环分析,如果是我们自己配置的bean就会走else中的getBean(beanName),接着看,会调用doGetBean方法,该方法太长,我们一段段看

        final String beanName = transformedBeanName(name);
        Object bean;

        // 先从缓存中取得Bean,处理那些已经被创建过的单例Bean,对这种Bean的请求不需要重复地创建
        Object sharedInstance = getSingleton(beanName);
        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 + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

我们可以进入到getSingleton方法,可以看到Spring会把实例化好的bean存入singletonObjects,这是一个ConcurrentHashMap
当然这里我们bean并未实例化过,所以这里应该也不能get出什么东西来,也就是返回null了。if子句也就不会执行了。那么接着看else子句的内容

        else {
            // Fail if we're already creating this bean instance: // We're assumably within a circular reference.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            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);
            }

这里对IoC容器中的BeanDefinition是否存在进行检查,检查是否存在双亲BeanFactory,如果存在则从双亲BeanFactory中实例化Bean,顺着双亲BeanFactory链一直向上。感觉跟类加载这么相似

  • 类加载机制的好处:java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪个类加载器要加载这个类,最终都会委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果用户自己写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,java类型体系中最基础的行为也无法保证,应用程序也会变得一片混乱

我们接着看:

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

                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                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);
                    }
                }
                ......
                createBean()

在这里拿到RootBeanDefinition并check,然后获得bean的依赖,并循环迭代实例化bean。例如class A依赖于class B,就会先实例化B,触发getBean的递归调用,直到取到最后一个Bean

其实真正实例化bean的方法是下面的createBean()=>doCreateBean()方法,又是一坨很长的代码,其中BeanWrapper是用来持有创建出来的Bean对象的,我们分为3个部分,一个个来分析

  • 创建Bean实例-createBeanInstance()
  • 依赖注入-populateBean()
  • 初始化Bean实例-initializeBean()
    首先看createBeanInstance()方法
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, 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());
        }
        //使用工厂方法对Bean进行实例化
        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);
            }
        }

        // Need to determine the constructor...
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        //使用默认构造函数对Bean进行实例化
        return instantiateBean(beanName, mbd);
    }

实现路径:instantiateBean=>SimpleInstantiationStrategy.instantiate,使用了策略模式,动态选择策略

    @Override
    public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
        // Don't override the class with CGLIB if no overrides.
        if (beanDefinition.getMethodOverrides().isEmpty()) {
            Constructor<?> constructorToUse;
            synchronized (beanDefinition.constructorArgumentLock) {
                constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {
                    final Class<?> clazz = beanDefinition.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                        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);
                        }
                        beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
                    }
                    catch (Exception ex) {
                        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
                }
            }
            return BeanUtils.instantiateClass(constructorToUse);
        }
        else {
            // Must generate CGLIB subclass.
            return instantiateWithMethodInjection(beanDefinition, beanName, owner);
        }
    }

上述判断beanDefinition.getMethodOverrides().isEmpty()和Spring配置lookup-method有关,具体参考http://www.cnblogs.com/mjorcen/p/3647209.html
该方法提供了两种实例化Bean的方法,一种是通过BeanUtils,它使用JVM的反射功能;一种是通过CGLIB来生成,CGLIB是一个常用的字节码生成器的类库,它提供了一系列的API来提供生成和转换Java的字节码功能

到这里已经分析了实例化Bean对象的整个过程,在实例化Bean对象生成的基础上,再介绍一下怎样把这些Bean对象的依赖关系设置好,完成整个依赖注入过程,这些依赖关系处理的依据就是已经解析得到的BeanDefinition。

接下来我们分析和createBeanInstance()方法平起平坐的populateBean()方法

    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();

        ......
        //1.处理bean定义上的autowire属性,可以来自于<bean>定义时autowire属性,也可以来自于整个xml定义中<beans>节点中的default-autowire属性
        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);
            }

            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
//2.处理注解@Component@Repository@Service@Controller@Autowired@Resource的地方,提取name、type等属性和方法后,存储到applyPropertyValues方法中变量pvs,供依赖注入使用
        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }

        applyPropertyValues(beanName, mbd, bw, pvs);
    }

注释中1和2可能会有点疑惑,具体参考http://jianhao-wang.iteye.com/blog/2146027
applyPropertyValues方法是对属性进行解析然后注入

    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if (pvs == null || pvs.isEmpty()) {
            return;
        }

        MutablePropertyValues mpvs = null;
        //original中包含了ref的name、type等属性和方法
        List<PropertyValue> original;

        if (System.getSecurityManager() != null) {
            if (bw instanceof BeanWrapperImpl) {
                ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
            }
        }

        if (pvs instanceof MutablePropertyValues) {
            mpvs = (MutablePropertyValues) pvs;
            if (mpvs.isConverted()) {
                // Shortcut: use the pre-converted values as-is.
                try {
                    bw.setPropertyValues(mpvs);
                    return;
                }
                catch (BeansException ex) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
                }
            }
            original = mpvs.getPropertyValueList();
        }
        else {
            original = Arrays.asList(pvs.getPropertyValues());
        }

        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

        // 这里为解析值创建一个副本,副本的数据将会被注入到bean中
        List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
        boolean resolveNecessary = false;
        for (PropertyValue pv : original) {
            if (pv.isConverted()) {
                deepCopy.add(pv);
            }
            else {
                String propertyName = pv.getName();
                Object originalValue = pv.getValue();
                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                Object convertedValue = resolvedValue;
                boolean convertible = bw.isWritableProperty(propertyName) &&
                        !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                if (convertible) {
                    convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
                }
                // Possibly store converted value in merged bean definition,
                // in order to avoid re-conversion for every created bean instance.
                if (resolvedValue == originalValue) {
                    if (convertible) {
                        pv.setConvertedValue(convertedValue);
                    }
                    deepCopy.add(pv);
                }
                else if (convertible && originalValue instanceof TypedStringValue &&
                        !((TypedStringValue) originalValue).isDynamic() &&
                        !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                    pv.setConvertedValue(convertedValue);
                    deepCopy.add(pv);
                }
                else {
                    resolveNecessary = true;
                    deepCopy.add(new PropertyValue(pv, convertedValue));
                }
            }
        }
        if (mpvs != null && !resolveNecessary) {
            mpvs.setConverted();
        }

        // Set our (possibly massaged) deep copy.
        try {
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Error setting property values", ex);
        }
    }

我们详细分析以下几个重要方法:

  • BeanDefinitionValueResolver.resolveValueIfNecessary可以解析各种各样的数据类型,但最终都会调用resolveReference()方法
    public Object resolveValueIfNecessary(Object argName, Object value) {
        // 这里对RuntimeBeanReference进行解析,RuntimeBeanReference是在对BeanDefinition进行解析时生成的数据对象
        if (value instanceof RuntimeBeanReference) {
            RuntimeBeanReference ref = (RuntimeBeanReference) value;
            return resolveReference(argName, ref);
        }
    /** * Resolve a reference to another bean in the factory. */
    private Object resolveReference(Object argName, RuntimeBeanReference ref) {
        try {
        //从RuntimeBeanReference取得reference的名字,这个RuntimeBeanReference是在载入BeanDefinition时根据配置生成的
            String refName = ref.getBeanName();
            refName = String.valueOf(evaluate(refName));
            //如果ref是在双亲IoC容器中,那就到双亲IoC容器中去获取
            if (ref.isToParent()) {
                if (this.beanFactory.getParentBeanFactory() == null) {
                    throw new BeanCreationException(
                            this.beanDefinition.getResourceDescription(), this.beanName,
                            "Can't resolve reference to bean '" + refName +
                            "' in parent factory: no parent factory available");
                }
                return this.beanFactory.getParentBeanFactory().getBean(refName);
            }
            else {
            //在当前IoC容器中去获取Bean,这里会触发一个getBean的过程,会触发ref的依赖注入,一层一层递归调用,直到第一个bean被实例化
                Object bean = this.beanFactory.getBean(refName);
                this.beanFactory.registerDependentBean(refName, this.beanName);
                return bean;
            }
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    this.beanDefinition.getResourceDescription(), this.beanName,
                    "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
        }
    }
  • BeanWrapper.setPropertyValues完成属性值注入(循环一个个注入)
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
...... try { //获取Bean中对注入对象的引用,ref propValue = getPropertyValue(getterTokens); } ......
}

我们来看最后一个和createBeanInstance、populateBean平起平坐的方法initializeBean,对创建的Bean实例进行初始化,看源码:

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                //设置Bean的名字、类加载器和自身所在的IoC容器
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
                //调用Bean的初始方法,这个初始方法是BeanDefinition中通过定义init-method属性指定的
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

注意这有两个方法applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization,里面的类继承了BeanPostProcessor接口,这个后置处理器是一个监听器,它可以监听容器触发的时间,将它向IoC容器注册后,容器中管理的Bean具备了接受IoC容器事件回调的能力,BeanPostProcessor两个方法

  1. 一个是postProcessBeforeInitialization,在Bean初始化前提供回调入口
  2. 一个是postProcessAfterInitialization,在Bean的初始化后提供回调入口
    这两个回调的触发都是和容器管理Bean的生命周期相关的

总结

在Bean的撞见和对象依赖注入的过程中,需要依据BeanDefinition的信息来递归完成依赖注入。从上面的几个递归过程中可以看到,这些递归都是以getBean为入口:

  1. 一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用
  2. 另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入,在对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。

转载请注明出处http://blog.csdn.net/qq418517226/article/details/42711067

    原文作者:Spring MVC
    原文地址: https://blog.csdn.net/qq418517226/article/details/51249117
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞