美文网首页
spring容器之创建bean实例

spring容器之创建bean实例

作者: 会上树的程序猿 | 来源:发表于2019-07-14 14:17 被阅读0次

    在上篇spring容器之开启bean的创建之旅中我们最后将创建bean的过程大致的总结了分八步走,这里就不啰嗦了,不知道的可以自己去看看,本篇主要的学习是对上节创建bean的每个步骤进行详细的学习,首先我们从创建bean的实例开始,代码如下:

    AbstractAutowireCapableBeanFactory.java
    
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // Make sure bean class is actually resolved at this point.
        //解析class
        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());
        }
        //<1>.获取创建bean实例的回调Supplier
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        //如果存在该回调,使用该回调策略来初始化bean实例
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }
        //<2>.如果工厂方法不为null,则使用工厂的方法的策略来初始化bean实例
        if (mbd.getFactoryMethodName() != null) {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }
    
        //<3>. Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            //使用constructorArgumentLock
            //该constructorArgumentLock为构造函数字段常用的锁
            synchronized (mbd.constructorArgumentLock) {
                //<3.1>.resolvedConstructorOrFactoryMethod用来缓存已解析的构造函数的字段和或工厂方法
                //如果不为null
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    //对该构造参数进行标记为已解析
                    //因为对于一个类可能有很多个构造函数,每个构造函数所需的参数可能不一样,所以在调用前需确定其参数方可
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        //如果解析完成,直接通过注入即可
        if (resolved) {
            //<3.2>.构造函数自动注入
            if (autowireNecessary) {
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                //<3.3>.使用默认构造函数进行构造
                return instantiateBean(beanName, mbd);
            }
        }
    
        // Candidate constructors for autowiring?
        //<4>.通过参数来解析构造器
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        //<4.1>.当args不为null时,通过参数的个数,类型等,做精确的构造方法的选择来创建bean
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            return autowireConstructor(beanName, mbd, ctors, args);
        }
    
        // Preferred constructors for default construction?
        //<4.2>.获取构造方法来构建bean
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            return autowireConstructor(beanName, mbd, ctors, null);
        }
    
        // No special handling: simply use no-arg constructor.
        //<4.3>.使用默认的构造函数构造
        return instantiateBean(beanName, mbd);
    }
    

    方法很长,但总体来说目的很明确,这里简单的小结一下:

    • 在<1>处,我们可以看到对创建bean实例过程中回调的获取
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        //如果存在该回调,使用该回调策略来初始化bean实例
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }
    

    当获取到的回调不为null时,发现调用#obtainFromSupplier(Supplier<?> instanceSupplier, String beanName)来初始化,跟踪代码来到:

    看代码之前先来了解一个java8里的特性Supplier<?>接口的东西,让大家有个认识,说实话好久没接触过了,直接看代码:

    @FunctionalInterface
    public interface Supplier<T> {
    
    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
    

    }

    Supplier实际上是一个供给接口,且只有一个get()方法,其实类似于spring的工厂方法.

    AbstractBeanDefinition.java
    private Supplier<?> instanceSupplier;
    public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
        this.instanceSupplier = instanceSupplier;
    }
    
    /**
     * Return a callback for creating an instance of the bean, if any.
     * @since 5.0
     */
    @Nullable
    public Supplier<?> getInstanceSupplier() {
        return this.instanceSupplier;
    }
    

    在AbstractBeanDefinition类中可以看到它的实例化过程,接下来我们来看回调的整个过程:

    /**保存当前创建bean的名字*/
    private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
    
    
    protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
        Object instance;
        //获取原先创建bean的名字
        String outerBean = this.currentlyCreatedBean.get();
        //保存新的bean的名字到currentlyCreatedBean中
        this.currentlyCreatedBean.set(beanName);
        try {
            //1.调用Supplier#get()方法获取bean实例
            instance = instanceSupplier.get();
        }
        finally {
            if (outerBean != null) {
                //如果原先bean存在,将保存到currentlyCreatedBean中
                this.currentlyCreatedBean.set(outerBean);
            }
            else {
                this.currentlyCreatedBean.remove();
            }
        }
        //2.如果没有创建对象时,则创建一个NullBean实例
        if (instance == null) {
            instance = new NullBean();
        }
        //3.初始化BeanWrapper对象
        BeanWrapper bw = new BeanWrapperImpl(instance);
        initBeanWrapper(bw);
        return bw;
    }
    

    简单的总结一下:

    • 调用我们指定的Supplier的get()方法获取bean的实例
    • 进行一些相关的设置操作
    • 如果没有创建对象,直接创建一个NullBean对象.
    • 最后是对BeanWrapper对象的创建以及初始化的操作
    • 在<2>处,我们可以看到的是,如果存在工厂方法,则通过#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)方法来完成bean的初始化过程,直接看代码:
    AbstractAutowireCapableBeanFactory.java
    
    protected BeanWrapper instantiateUsingFactoryMethod(
            String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    
        return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
    }
    

    我们可以方法首先需要构造一个ConstructorResolver对象,然后调用该实例的#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)方法构建bean实例,接着看:

    ConstructorResolver.java
    public BeanWrapper instantiateUsingFactoryMethod(
            String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
        //1.构建并实例化BeanWrapperImpl对象
        BeanWrapperImpl bw = new BeanWrapperImpl();
        this.beanFactory.initBeanWrapper(bw);
        //2.获取factoryBean factoryClass和isStatic等属性
        Object factoryBean;
        Class<?> factoryClass;
        boolean isStatic;
        //2.1.获取factoryBeanName属性
        String factoryBeanName = mbd.getFactoryBeanName();
        //factoryBeanName存在,且跟当前bean的名字一样,直接抛BeanDefinitionStoreException异常
        if (factoryBeanName != null) {
            if (factoryBeanName.equals(beanName)) {
                throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                        "factory-bean reference points back to the same bean definition");
            }
            //不一样的情况下
            //2.2.获取factory实例
            factoryBean = this.beanFactory.getBean(factoryBeanName);
    
            if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
                throw new ImplicitlyAppearedSingletonException();
            }
            //2.3.获取factoryClass属性
            factoryClass = factoryBean.getClass();
            isStatic = false;
        }
        //2.3.此处可能是静态工厂方法
        //因为静态工厂创建bean时,需要提供工厂的全类名
        else {
            // It's a static factory method on the bean class.
            if (!mbd.hasBeanClass()) {
                throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                        "bean definition declares neither a bean class nor a factory-bean reference");
            }
            factoryBean = null;
            factoryClass = mbd.getBeanClass();
            isStatic = true;
        }
        //3.获取工厂属性factoryMethodToUse ArgumentsHolder和argsToUse
    
        Method factoryMethodToUse = null;//工厂方法
        ArgumentsHolder argsHolderToUse = null;
        Object[] argsToUse = null;//参数
        //3.1.explicitArgs参数通过getBean方法传入
        //如果在构建bean时指定了构造器,那么直接使用该参数
        if (explicitArgs != null) {
            argsToUse = explicitArgs;
        }
        //3.2.没有指定的话,尝试着从配置文件中解析
        else {
            Object[] argsToResolve = null;
            //给公用构造方法加锁
            synchronized (mbd.constructorArgumentLock) {
                //从缓存中尝试着获取
                factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
                //从缓存中获取argsToUse属性
                if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                    // Found a cached factory method...
                    argsToUse = mbd.resolvedConstructorArguments;
                    //从缓存中没有获取到
                    if (argsToUse == null) {
                        //获取构造函数的可见字段
                        argsToResolve = mbd.preparedConstructorArguments;
                    }
                }
            }
            //3.3.缓存中存在
            //解析在beanDefinition中的参数类型,解析的过程大致如下:
            //如给定方法的构造函数 A(int ,int ),则通过此方法后就会把配置文件中的("1","1")转换为 (1,1)
            //缓存中的值可能是原始值也有可能是最终值
            if (argsToResolve != null) {
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
            }
        }
    
        //4.没有被缓存
        if (factoryMethodToUse == null || argsToUse == null) {
            // Need to determine the factory method...
            // Try all methods with this name to see if they match the given arguments.
            //4.1.获取全限定名
            factoryClass = ClassUtils.getUserClass(factoryClass);
    
            List<Method> candidateList = null;
            //4.2.检测方法名是否是唯一性
            if (mbd.isFactoryMethodUnique) {
                if (factoryMethodToUse == null) {
                    factoryMethodToUse = mbd.getResolvedFactoryMethod();
                }
                if (factoryMethodToUse != null) {
                    candidateList = Collections.singletonList(factoryMethodToUse);
                }
            }
            if (candidateList == null) {
                candidateList = new ArrayList<>();
                //4.3.获取所有符合条件的方法
                Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
                //遍历符合条件是static的方法那么就添加到candidateList中
                for (Method candidate : rawCandidates) {
                    if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                        candidateList.add(candidate);
                    }
                }
            }
    
            //4.4创建bean实例
            if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
                Method uniqueCandidate = candidateList.get(0);
                if (uniqueCandidate.getParameterCount() == 0) {
                    //缓存内省工厂方法
                    mbd.factoryMethodToIntrospect = uniqueCandidate;
                    synchronized (mbd.constructorArgumentLock) {
                        mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                        mbd.constructorArgumentsResolved = true;
                        mbd.resolvedConstructorArguments = EMPTY_ARGS;
                    }
                    //封装bean
                    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
                    return bw;
                }
            }
    
            Method[] candidates = candidateList.toArray(new Method[0]);
            //对构造的工厂方法进行排序
            //排序规则是:优先是public的,之后是非公共的
            AutowireUtils.sortFactoryMethods(candidates);
    
            ConstructorArgumentValues resolvedValues = null;
            boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
            int minTypeDiffWeight = Integer.MAX_VALUE;
            Set<Method> ambiguousFactoryMethods = null;
    
            int minNrOfArgs;
            if (explicitArgs != null) {
                minNrOfArgs = explicitArgs.length;
            }
            else {
                // We don't have arguments passed in programmatically, so we need to resolve the
                // arguments specified in the constructor arguments held in the bean definition.
                //4.5.获取构造函数的参数
                if (mbd.hasConstructorArgumentValues()) {
                    ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                    //用来承载解析后的参数的值
                    resolvedValues = new ConstructorArgumentValues();
                    //解析参数
                    minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
                }
                else {
                    minNrOfArgs = 0;
                }
            }
            //4.6.遍历方法
            LinkedList<UnsatisfiedDependencyException> causes = null;
    
            for (Method candidate : candidates) {
                //获取方法体上的参数
                Class<?>[] paramTypes = candidate.getParameterTypes();
                //
                if (paramTypes.length >= minNrOfArgs) {
                    //保存参数对象
                    ArgumentsHolder argsHolder;
                    //explicitArgs为getBean方法的参数
                    if (explicitArgs != null) {
                        // Explicit arguments given -> arguments length must match exactly.
                        //显示给定参数,参数的长度必须匹配
                        if (paramTypes.length != explicitArgs.length) {
                            continue;
                        }
                        //根据参数去构建参数的持有者ArgumentsHolder对象
                        argsHolder = new ArgumentsHolder(explicitArgs);
                    }
                    //构建bean的explicitArgs为null
                    else {
                        // Resolved constructor arguments: type conversion and/or autowiring necessary.
                        //为了提供必须的参数,解析参数
                        try {
                            String[] paramNames = null;
                            //获取ParameterNameDiscoverer对象
                            //ParameterNameDiscoverer为解析方法和构造函数的参数的接口
                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                            //如果存在,获取构造器的所有参数
                            if (pnd != null) {
                                paramNames = pnd.getParameterNames(candidate);
                            }
                            //在给定已解析的构造函数参数值的情况下,创建一个参数ArgumentsHolder的持有者对象
                            argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
                                    paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
                        }
                        //在创建的过程中,如果抛UnsatisfiedDependencyException异常,保存到causes中
                        catch (UnsatisfiedDependencyException ex) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
                            }
                            // Swallow and try next overloaded factory method.
                            if (causes == null) {
                                causes = new LinkedList<>();
                            }
                            causes.add(ex);
                            //继续执行
                            continue;
                        }
                    }
    
                    //5.通过isLenientConstructorResolution来判断解析的构造方法是宽松模式还是严格模式
                    //如果是宽松模式:采用最接近的来匹配解析
                    //如果是严格模式:所有的都要匹配上才可以
                    //typeDiffWeight:获取类型差异权重
                    int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                    // Choose this factory method if it represents the closest match.
                    //匹配最接近的构造函数,以下为作为该构造函数的参数
                    if (typeDiffWeight < minTypeDiffWeight) {
                        factoryMethodToUse = candidate;
                        argsHolderToUse = argsHolder;
                        argsToUse = argsHolder.arguments;
                        minTypeDiffWeight = typeDiffWeight;
                        ambiguousFactoryMethods = null;
                    }
                    // Find out about ambiguity: In case of the same type difference weight
                    // for methods with the same number of parameters, collect such candidates
                    // and eventually raise an ambiguity exception.
                    // However, only perform that check in non-lenient constructor resolution mode,
                    // and explicitly ignore overridden methods (with the same parameter signature).
                    // 如果具有相同参数数量的方法具有相同的类型差异权重,则收集此类型选项
                    // 但是,仅在非宽松构造函数解析模式下执行该检查,并显式忽略重写方法(具有相同的参数签名)
                    else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
                            !mbd.isLenientConstructorResolution() &&
                            paramTypes.length == factoryMethodToUse.getParameterCount() &&
                            !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
                        //获取到多个可以匹配的方法
                        if (ambiguousFactoryMethods == null) {
                            ambiguousFactoryMethods = new LinkedHashSet<>();
                            ambiguousFactoryMethods.add(factoryMethodToUse);
                        }
                        ambiguousFactoryMethods.add(candidate);
                    }
                }
            }
    
            //6. 没有可执行的方法时,直接抛UnsatisfiedDependencyException异常
            if (factoryMethodToUse == null || argsToUse == null) {
                if (causes != null) {
                    UnsatisfiedDependencyException ex = causes.removeLast();
                    for (Exception cause : causes) {
                        this.beanFactory.onSuppressedException(cause);
                    }
                    throw ex;
                }
                List<String> argTypes = new ArrayList<>(minNrOfArgs);
                //遍历explicitArgs参数数组
                if (explicitArgs != null) {
                    for (Object arg : explicitArgs) {
                        //如果遍历到的参数不为null,获取参数名,然后保存,为null,直接保存null即可
                        argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                    }
                }
                else if (resolvedValues != null) {
                    Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
                    valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
                    valueHolders.addAll(resolvedValues.getGenericArgumentValues());
                    for (ValueHolder value : valueHolders) {
                        String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
                                (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
                        argTypes.add(argType);
                    }
                }
                //对argTypes进行转换
                String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "No matching factory method found: " +
                        (mbd.getFactoryBeanName() != null ?
                            "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
                        "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
                        "Check that a method with the specified name " +
                        (minNrOfArgs > 0 ? "and arguments " : "") +
                        "exists and that it is " +
                        (isStatic ? "static" : "non-static") + ".");
            }
            else if (void.class == factoryMethodToUse.getReturnType()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Invalid factory method '" + mbd.getFactoryMethodName() +
                        "': needs to have a non-void return type!");
            }
            else if (ambiguousFactoryMethods != null) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Ambiguous factory method matches found in bean '" + beanName + "' " +
                        "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
                        ambiguousFactoryMethods);
            }
            //将解析后的构造函数保存到缓存中
    
            if (explicitArgs == null && argsHolderToUse != null) {
                mbd.factoryMethodToIntrospect = factoryMethodToUse;
                argsHolderToUse.storeCache(mbd, factoryMethodToUse);
            }
        }
        //创建bean对象,并保存到bw中
        bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
        return bw;
    }
    

    呜呜呜,这个方法好长呀,看的也是懵逼,硬着头皮看的,而且过程也很复杂,我看完之后也没啥影响了,再来一遍,好像在方法的整个过程中,都是对工厂对象的构造函数和参数展开,通过匹配最接近的构造函数,在方法的末尾调用#instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Constructor<?> ctor, Object... args) 方法来建bean对象.我们在对该方法进行总结一下:

    • 在1.处是首先是对BeanWrapperImpl对象的创建和初始化,以备后面bean的创建完成后进行封装
    • 在2.处,获取工厂bean的一些参数和方法,如:factoryBeanName和factoryClass和isStatic等属性
    • 在2.1.处是对factoryBeanName的获取以及简单的处理操作
        String factoryBeanName = mbd.getFactoryBeanName();
        //factoryBeanName存在,且跟当前bean的名字一样,直接抛BeanDefinitionStoreException异常
        if (factoryBeanName != null) {
            if (factoryBeanName.equals(beanName)) {
                throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                        "factory-bean reference points back to the same bean definition");
            }
    

    我们可以看到是通过beanDefinition来获取factoryBean的name属性,这也是符合的,我们知道beanDefinition就是描述一个bean的定义

    • 在2.2.处是获取factory实例
    factoryBean = this.beanFactory.getBean(factoryBeanName);
    
            if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
                throw new ImplicitlyAppearedSingletonException();
            }
    

    是通过#getBean()来获取的,此方法最后是通过AbstractAutowireCapableBeanFactory#getBean(String name)来实现,关于此方法的学习我们前面已经说了,这里就不啰嗦了,这里我们需要注意的一点是:
    上述获取到的factory是因为工厂的方法不为null的情况下.再来看另外一种情况.

    • 2.3.处,那么就是一个静态工厂了,需要提供类的全限定名才能获取factory对象
    • 在3.处实际上是对工厂工造参数的确定,其主要是通过explicitArgs是否为null来判断

    注意:explicitArgs主要是我们在调用#getBean方法时,由用户直接指定构造函数来创建对象的参数,它不为null,那么我们的构造函数就确认了

    • 在3.2处,当explicitArgs为null时,从配置文件中解析获取
    .....省略很多代码.....
    
    Object[] argsToResolve = null;
            //给公用构造方法加锁
            synchronized (mbd.constructorArgumentLock) {
                //从缓存中尝试着获取
                factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
                //从缓存中获取argsToUse属性
                if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                    // Found a cached factory method...
                    argsToUse = mbd.resolvedConstructorArguments;
                    //从缓存中没有获取到
                    if (argsToUse == null) {
                        //获取构造函数的可见字段
                        argsToResolve = mbd.preparedConstructorArguments;
                    }
                }
            }
    

    都是从我们的beanDefinition中尝试着获取,简单的来说一下:

    <1>. 首先是从resolvedConstructorOrFactoryMethod获取,该缓存主要保存的是已经解析过的构造方法或者是工厂方法
    <2> . 从resolvedConstructorArguments中获取已经完全解析的构造函数的参数
    <3>. 从preparedConstructorArguments中获取已经准备好的部分构造参数以备构造方法使用

    • 在3.3.处,上述的参数我们在缓存中获取到了,解析部分构造函数所需的参数,调用#resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,Executable executable, Object[] argsToResolve, boolean fallback)方法来完成
    if (argsToResolve != null) {
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
            }
    

    当argsToResolve存在的情况下,接着看:

    private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
            Executable executable, Object[] argsToResolve, boolean fallback) {
        //获取TypeConverter对象
        TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
        //存在的话,就用自定义的TypeConverter,不存在的话用BeanWrapper来代替
        TypeConverter converter = (customConverter != null ? customConverter : bw);
        //这里的beanFactory为AbstractAutowireCapableBeanFactory
        //构建BeanDefinitionValueResolver解析器
        BeanDefinitionValueResolver valueResolver =
                new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
        //获取参数的类型
        Class<?>[] paramTypes = executable.getParameterTypes();
        //解析处理过程
        Object[] resolvedArgs = new Object[argsToResolve.length];
        for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
            Object argValue = argsToResolve[argIndex];
            //通过参数的索引和构造函数来创建MethodParameter对象
            MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
            //解析参数的类型
            GenericTypeResolver.resolveParameterType(methodParam, executable.getDeclaringClass());
            //argValue是AutowiredArgumentMarker
            //调用resolveAutowiredArgument去解析处理
            if (argValue instanceof AutowiredArgumentMarker) {
                argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback);
            }
            //如果是BeanMetadataElement类型的
            //调用resolveValueIfNecessary去解析处理
            else if (argValue instanceof BeanMetadataElement) {
                argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
            }
            //字符串类型的
            //通过AbstractAutowireCapableBeanFactory#evaluateBeanDefinitionString方法去处理
            else if (argValue instanceof String) {
    
                argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
            }
            //保存
            Class<?> paramType = paramTypes[argIndex];
            try {
                //对解析后的参数进行转换
                //规则为:如给定方法的构造函数 A(int ,int ),则通过此方法后就会把配置文件中的("1","1")转换为 (1,1)
                resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
            }
            catch (TypeMismatchException ex) {
                throw new UnsatisfiedDependencyException(
                        mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
                        "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) +
                        "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
            }
        }
        return resolvedArgs;
    }
    

    在该方法的最后我们发现,对于不同类型的参数类型,对应着不同的处理方法.
    最后进行参数的转化

    • 在4处,如果工厂没有被缓存,可能是静态工厂
    • 4.1.处首先是获取factory的全限定名并进行唯一性的检查
    • 4.3.处获取所有符合条件的方法
    Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
    //遍历符合条件是static的方法那么就添加到candidateList中
      for (Method candidate : rawCandidates) {
        if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                    candidateList.add(candidate);
                    }
                }
    
    • 在4.4处创建bean对象并封装
      List<Method> candidateList = null;
    if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
                Method uniqueCandidate = candidateList.get(0);
                if (uniqueCandidate.getParameterCount() == 0) {
                    //缓存内省工厂方法
                    mbd.factoryMethodToIntrospect = uniqueCandidate;
                    synchronized (mbd.constructorArgumentLock) {
                        mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                        mbd.constructorArgumentsResolved = true;
                        mbd.resolvedConstructorArguments = EMPTY_ARGS;
                    }
                    //封装bean
                    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
                    return bw;
                }
            }
    

    在此处是创建bean实例的地方,核心方法#instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, @Nullable Object... args)来创建,因为我们的工厂对象以及构造函数和参数已经确定了,接着看:

    private Object instantiate(String beanName, RootBeanDefinition mbd,
            @Nullable Object factoryBean, Method factoryMethod, Object[] args) {
    
        try {
            //首先是获取当前系统的安全环境管理器
            //存在的话在当前环境下创建
            if (System.getSecurityManager() != null) {
                return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                        this.beanFactory.getInstantiationStrategy().instantiate(
                                mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
                        this.beanFactory.getAccessControlContext());
            }
            //直接创建
            else {
                return this.beanFactory.getInstantiationStrategy().instantiate(
                        mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean instantiation via factory method failed", ex);
        }
    }
    

    我们可以发现首先是对系统的当前环境的检测,如:是否有访问权限等,然后真正的核心创建bean实例的方法是InstantiationStrategy#instantiate()方法,接着看:

    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
            @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    
        try {
            //设置方法的访问权限
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    ReflectionUtils.makeAccessible(factoryMethod);
                    return null;
                });
            }
            else {
                ReflectionUtils.makeAccessible(factoryMethod);
            }
            //获取之前的方法
            Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
            try {
                //将新的工厂方法保存到currentlyInvokedFactoryMethod中
                currentlyInvokedFactoryMethod.set(factoryMethod);
                //创建bean对象
                Object result = factoryMethod.invoke(factoryBean, args);
                //没创建成功,则创建一个nullBean来代替
                if (result == null) {
                    result = new NullBean();
                }
                //创建成功的话,直接返回
                return result;
            }
            finally {
                if (priorInvokedFactoryMethod != null) {
                    //覆盖之前的方法
                    currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
                }
                else {
                    currentlyInvokedFactoryMethod.remove();
                }
            }
        }
        catch (IllegalArgumentException ex) {
            throw new BeanInstantiationException(factoryMethod,
                    "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
                    "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
        }
        catch (IllegalAccessException ex) {
            throw new BeanInstantiationException(factoryMethod,
                    "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
        }
        catch (InvocationTargetException ex) {
            String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
            if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
                    ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
                msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
                        "declaring the factory method as static for independence from its containing instance. " + msg;
            }
            throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
        }
    }
    

    该方法其实就一个核心点,通过反射的方式来创建对象

    Object result = factoryMethod.invoke(factoryBean, args);
    

    其实到这一步了我们的目标也达到了,后面的无非还是一些参数的验证和匹配最接近的构造函数,最后还是调用#instantiate来创建bean对象,其中包括一些解析参数的方法如:#resolveConstructorArguments()方法和#createBeanInstance(...)方法可以去看看,我这里就不说了,那么关于创建bean实例的篇幅就到这里了

    相关文章

      网友评论

          本文标题:spring容器之创建bean实例

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