bean的创建(五)第四部分 bean构造器的查找

摘要:
对象[]args){//Makesurebeanclass在此点实际解析。Class<=null&Modifier.isPublic(beanClass.getModifiers())&
前面分析了bean的静态工厂查找
bean的构造器查找过程和bean的静态工厂查找类似

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

        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...通过后置处理器返回构造器,然后通过autowireConstructor去筛选构造器,这种可用于配置文件中没有配置构造器参数的方式。
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
//使用无参构造器构造
        return instantiateBean(beanName, mbd);
    }


AbstractAutowireCapableBeanFactory.autowireConstructor

protected BeanWrapper autowireConstructor(
            String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {

        return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
    }



ConstructorResolver.autowireConstructor

//beanName表示正在创建bean的名字,mbd表示正在创建bean的BeanDefinition,chosenCtors表示是程序指定的可选构造器列表,可通过后置处理器得到,explicitArgs是用户指定的构造参数
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
            Constructor<?>[] chosenCtors, final Object[] explicitArgs) {

        BeanWrapperImpl bw = new BeanWrapperImpl();
//初始化,注册类型转化器和自定义类型转化器
        this.beanFactory.initBeanWrapper(bw);

        Constructor<?> constructorToUse = null;
        ArgumentsHolder argsHolderToUse = null;
        Object[] argsToUse = null;

        if (explicitArgs != null) {
            argsToUse = explicitArgs;
        }
        else {
//这里的操作和解析工厂方法时一样的
            Object[] argsToResolve = null;
            synchronized (mbd.constructorArgumentLock) {
//从缓存中获取
                constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse != null && mbd.constructorArgumentsResolved) {
                    // Found a cached constructor...
                    argsToUse = mbd.resolvedConstructorArguments;
                    if (argsToUse == null) {
//使用预备的集合参数
                        argsToResolve = mbd.preparedConstructorArguments;
                    }
                }
            }
            if (argsToResolve != null) {
//解析预备参数集合
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
            }
        }

//如果没有缓存,那么就从头开始查找
        if (constructorToUse == null) {
            // Need to resolve the constructor.
//如果用户指定了构造器,或者装配为构造器自动装配
            boolean autowiring = (chosenCtors != null ||
                    mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
            ConstructorArgumentValues resolvedValues = null;

            int minNrOfArgs;
            if (explicitArgs != null) {
                minNrOfArgs = explicitArgs.length;
            }
            else {
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                resolvedValues = new ConstructorArgumentValues();
//解析配置的参数
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
            }

            // Take specified constructors, if any.
            Constructor<?>[] candidates = chosenCtors;
            if (candidates == null) {

                Class<?> beanClass = mbd.getBeanClass();
                try {
//如果没有指定构造器,那么就获取当前bean的构造器
                    candidates = (mbd.isNonPublicAccessAllowed() ?
                            beanClass.getDeclaredConstructors() : beanClass.getConstructors());
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                                    "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }
            }
//进行排序,public在前,参数长的在前
            AutowireUtils.sortConstructors(candidates);
            int minTypeDiffWeight = Integer.MAX_VALUE;
            Set<Constructor<?>> ambiguousConstructors = null;
            LinkedList<UnsatisfiedDependencyException> causes = null;

            for (int i = 0; i < candidates.length; i++) {
                Constructor<?> candidate = candidates[i];
                Class<?>[] paramTypes = candidate.getParameterTypes();

                if (constructorToUse != null && argsToUse.length > paramTypes.length) {
                    // Already found greedy constructor that can be satisfied ->
                    // do not look any further, there are only less greedy constructors left.
                    break;
                }
                if (paramTypes.length < minNrOfArgs) {
                    continue;
                }

                ArgumentsHolder argsHolder;
                if (resolvedValues != null) {
                    try {
                        String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                        if (paramNames == null) {
                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                            if (pnd != null) {
                                paramNames = pnd.getParameterNames(candidate);
                            }
                        }
                        argsHolder = createArgumentArray(
                                beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
                    }
                    catch (UnsatisfiedDependencyException ex) {
                        if (this.beanFactory.logger.isTraceEnabled()) {
                            this.beanFactory.logger.trace(
                                    "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
                        }
                        // Swallow and try next constructor.
                        if (causes == null) {
                            causes = new LinkedList<UnsatisfiedDependencyException>();
                        }
                        causes.add(ex);
                        continue;
                    }
                }
                else {
                    // Explicit arguments given -> arguments length must match exactly.
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    argsHolder = new ArgumentsHolder(explicitArgs);
                }
//根据一些宽松或者严格模式去寻找更适合的构造器
                int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                        argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                // Choose this constructor if it represents the closest match.
                if (typeDiffWeight < minTypeDiffWeight) {
                    constructorToUse = candidate;
                    argsHolderToUse = argsHolder;
                    argsToUse = argsHolder.arguments;
                    minTypeDiffWeight = typeDiffWeight;
                    ambiguousConstructors = null;
                }
                else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
                    if (ambiguousConstructors == null) {
                        ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
                        ambiguousConstructors.add(constructorToUse);
                    }
//存储存在歧义的构造器
                    ambiguousConstructors.add(candidate);
                }
            }

            if (constructorToUse == null) {
                if (causes != null) {
                    UnsatisfiedDependencyException ex = causes.removeLast();
                    for (Exception cause : causes) {
                        this.beanFactory.onSuppressedException(cause);
                    }
                    throw ex;
                }
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Could not resolve matching constructor " +
                        "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
            }
            else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Ambiguous constructor matches found in bean '" + beanName + "' " +
                        "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
                        ambiguousConstructors);
            }

            if (explicitArgs == null) {
                argsHolderToUse.storeCache(mbd, constructorToUse);
            }
        }

        try {
            Object beanInstance;

            if (System.getSecurityManager() != null) {
                final Constructor<?> ctorToUse = constructorToUse;
                final Object[] argumentsToUse = argsToUse;
                beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        return beanFactory.getInstantiationStrategy().instantiate(
                                mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
                    }
                }, beanFactory.getAccessControlContext());
            }
            else {
//构造对应的bean实例
                beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
                        mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
            }

            bw.setWrappedInstance(beanInstance);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean instantiation via constructor failed", ex);
        }
    }

免责声明:文章转载自《bean的创建(五)第四部分 bean构造器的查找》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇网络编程(InetAddress类、UDP、TCP)delphi中的常用数学函数下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

使用 MVVMLight 绑定数据(转)

MVVMLight绑定数据示例 好了,我们在新建了两个项目,分别是“MVVMLight的主程序” 与  “Model层”,运行的效果及解决方案结构如下: 其实很简单,就是绑定了一个数据源而已,编写的代码也不多,下面我们来一步一步的实现使用MVVMLight来绑定数据,并了解其中的细节。 如何实现? 我这里使用的是.NET 4.5  , 你可以使用至少4....

uni-app中使用scroll-view滚到底部时多次触发scrolltolower

一、前言、scroll-view基本属性: 前言:   前段时间使用scroll-view可滚动视图区域容器来做多个不同内容的展示(在我这个页面中同时使用了三个scroll-view做数据展示),因为这几个展示的内容的数据都比较的多,因此为了页面的数据加载顺畅决定使用上拉加载(简单的说就是数据分页显示)。 页面组成如下图所示: scroll-view属性...

在vue 项目中嵌入jsp页面

今日一个项目中一块功能模块是其他系统使用jsp已经开发好的页面,想着直接将其嵌入到当前的vue项目中节约开发成本;但是发现并非想象的那么简单 创建一个server.vue组件加载jsp页面 1 、第一种(使用 v-html进行jsp 渲染) server.vue <template> <div class="docker-serve...

abort函数

函数名: abort 功 能: 异常终止一个进程 用 法: void abort(void); 程序例:   #include <stdio.h>     #include <stdlib.h>     int main(void)   {     printf("Calling abort()\n");       abort()...

EasyUI 页面分页

DAO package com.hanqi.dao; import java.util.ArrayList; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction...

JAVASCRIPT加密方法,JS加密解密综述(7种)

一:最简单的加密解密 对于JAVASCRIPT函数escape()和unescape()想必是比较了解啦(很多网页加密在用它们),分别是编码和解码字符串,比如例子代码 用escape()函数加密后变为如下格式: alert%28%22%u9ED1%u5BA2%u9632%u7EBF%22%29%3B 如何?还看的懂吗?当然其中的ASCII字符"alert...