【Spring IOC】【三】容器源码解析- 创建原始Bean

1  前言

上一文,我们讲解了getBean里的一些过程,这节我们详细来讲一讲创建bean,也就是createBean。createBean默认的实现类是AbstractAutowireCapableBeanFactory,createBean会调用doCreateBean和createBeanInstance,从这三个方法里大概总结出创建bean的集中方式:

  • 自定义BeanPostProcessor,生成代理对象InstantiationAwareBeanPostProcessor
    • createBean() -> resolveBeforeInstantiation()
  • 通过supplier创建对象
    • createBean() -> doCreateBean() -> createBeanInstance() -> obtainFromSupplier()
  • 通过FactoryMethod创建对象
    • createBean() -> doCreateBean() -> createBeanInstance() -> instantiateUsingFactoryMethod()
  • 通过构造方法创建对象
    • createBean() -> doCreateBean() -> createBeanInstance() -> autowireConstructor() 
  • 通过FactoryBean创建对象

2  源码分析

2.1  方法通读

针对createBeanInstance,我们来通读一下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 根据beanName以及bean定义信息得到beanClass 里边会涉及SPEL表达式的解析
        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定义文件mbd提供了Supplier 这样的函数接口 就通过函数接口去创建bean
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }
        // 如果bean描述文件mbd中提供了FactoryMethod工厂方法 那么就通过FactoryMethod创建bean
        if (mbd.getFactoryMethodName() != null) {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        /*
         * 加锁 多次构建同一个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) {
                // 通过构造方法创建bean
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 通过默认的构造方法反射创建bean
                return instantiateBean(beanName, mbd);
            }
        }

        // 由后置处理器决定返回哪些构造方法,这里不深入分析了
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        /*
         * 下面的条件分支条件用于判断使用什么方式构造 bean 实例,
         * 有两种方式可选 - 构造方法自动注入和默认构造方法。判断的条件由4部分综合而成,如下:
         *    条件1:ctors != null -> 后置处理器返回构造方法数组是否为空
         *    条件2:mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR
         *              -> bean 配置中的 autowire 属性是否为 constructor
         *    条件3:mbd.hasConstructorArgumentValues()
         *              -> constructorArgumentValues 是否存在元素,即 bean 配置文件中
         *                 是否配置了 <construct-arg/>
         *    条件4:!ObjectUtils.isEmpty(args)
         *              -> args 数组是否存在元素,args 是由用户调用
         *                 getBean(String name, Object... args) 传入的
         * 上面4个条件,只要有一个为 true,就会通过构造方法自动注入的方式构造 bean 实例
         */
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            // 通过“构造方法自动注入”的方式构造 bean 对象
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            // 通过“构造方法自动注入”的方式构造 bean 对象
            return autowireConstructor(beanName, mbd, ctors, null);
        }

        // 通过“默认构造方法”的方式构造 bean 对象
        return instantiateBean(beanName, mbd);
    }

看着这个方法表面的东西不多,实际上很多很多,他的方法调用一层一层调的好多,不打几个断点,多debug几次根本看不懂都是干啥的= =,所以看的时候要写个测试类测一测,打打断点自己调试调试,看变量、参数的变化,那么总结一下这个方法的执行流程,如下:

  • 解析bean的定义信息
  • 访问权限检查,若禁止访问,则抛出异常
  • 如果bean定义文件mbd提供了Supplier 这样的函数接口 就通过函数接口去创建bean
  • 如果bean描述文件mbd中提供了FactoryMethod工厂方法 那么就通过FactoryMethod创建bean
  • 若构造方式已解析过,则走快捷路径构建 bean 对象,并返回结果
  • 组合条件决定使用哪种方式构建 bean 对象

接下来我们大概分析一下每个创建的实现源码。

2.2  autowireConstructor-通过构造方法创建 bean 实例

根据你提供的构造方法,参数列表,寻找一个合适的构造器的过程:

  1 public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
  2             @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
  3 
  4         // 创建bean最后都会返回一个BeanWrapper类型的结果
  5         BeanWrapperImpl bw = new BeanWrapperImpl();
  6         this.beanFactory.initBeanWrapper(bw);
  7 
  8         Constructor<?> constructorToUse = null;
  9         ArgumentsHolder argsHolderToUse = null;
 10         Object[] argsToUse = null;
 11 
 12         if (explicitArgs != null) {
 13             argsToUse = explicitArgs;
 14         }
 15         else {
 16             Object[] argsToResolve = null;
 17             synchronized (mbd.constructorArgumentLock) {
 18                 // 获取bean定义信息中有没有解析过的用于构造bean的方法  第一次创建肯定是空的
 19                 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
 20                 if (constructorToUse != null && mbd.constructorArgumentsResolved) {
 21                     // 获取解析过的构造方法参数列表
 22                     argsToUse = mbd.resolvedConstructorArguments;
 23                     if (argsToUse == null) {
 24                         argsToResolve = mbd.preparedConstructorArguments;
 25                     }
 26                 }
 27             }
 28             if (argsToResolve != null) {
 29                 // 解析参数列表
 30                 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
 31             }
 32         }
 33 
 34         if (constructorToUse == null || argsToUse == null) {
 35             //获取当前bean的构造方法
 36             Constructor<?>[] candidates = chosenCtors;
 37             if (candidates == null) {
 38                 Class<?> beanClass = mbd.getBeanClass();
 39                 try {
 40                     candidates = (mbd.isNonPublicAccessAllowed() ?
 41                             beanClass.getDeclaredConstructors() : beanClass.getConstructors());
 42                 }
 43                 catch (Throwable ex) {
 44                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 45                             "Resolution of declared constructors on bean Class [" + beanClass.getName() +
 46                             "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
 47                 }
 48             }
 49             /*
 50                 当发现构造方法只有一个,且参数为空 那么就调用默认构造方法返回
 51              */
 52             if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
 53                 Constructor<?> uniqueCandidate = candidates[0];
 54                 if (uniqueCandidate.getParameterCount() == 0) {
 55                     synchronized (mbd.constructorArgumentLock) {
 56                         mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
 57                         mbd.constructorArgumentsResolved = true;
 58                         mbd.resolvedConstructorArguments = EMPTY_ARGS;
 59                     }
 60                     bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
 61                     return bw;
 62                 }
 63             }
 64 
 65             // 下边就需要解析每个构造器,选一个最优的构造器
 66             boolean autowiring = (chosenCtors != null ||
 67                     mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
 68             ConstructorArgumentValues resolvedValues = null;
 69 
 70             int minNrOfArgs;
 71             if (explicitArgs != null) {
 72                 minNrOfArgs = explicitArgs.length;
 73             }
 74             else {
 75                 // 解析构造参数 minNrOfArgs参数个数
 76                 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
 77                 resolvedValues = new ConstructorArgumentValues();
 78                 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
 79             }
 80             // 排序
 81             AutowireUtils.sortConstructors(candidates);
 82             int minTypeDiffWeight = Integer.MAX_VALUE;
 83             Set<Constructor<?>> ambiguousConstructors = null;
 84             Deque<UnsatisfiedDependencyException> causes = null;
 85             // 这里就要遍历每一个构造器 进行匹配选择
 86             // 原则就是访问权限最高的 参数匹配的上的
 87             for (Constructor<?> candidate : candidates) {
 88                 int parameterCount = candidate.getParameterCount();
 89 
 90                 if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
 91                     break;
 92                 }
 93 
 94                 if (parameterCount < minNrOfArgs) {
 95                     continue;
 96                 }
 97 
 98                 ArgumentsHolder argsHolder;
 99                 Class<?>[] paramTypes = candidate.getParameterTypes();
100                 if (resolvedValues != null) {
101                     try {
102                         // 构造方法的ConstructorProperties注解
103                         String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
104                         if (paramNames == null) {
105                             ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
106                             if (pnd != null) {
107                                 // 构造方法参数名字列表
108                                 paramNames = pnd.getParameterNames(candidate);
109                             }
110                         }
111                         // 构造方法参数值的解析
112                         argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
113                                 getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
114                     }
115                     catch (UnsatisfiedDependencyException ex) {
116                         if (logger.isTraceEnabled()) {
117                             logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
118                         }
119                         if (causes == null) {
120                             causes = new ArrayDeque<>(1);
121                         }
122                         causes.add(ex);
123                         continue;
124                     }
125                 }
126                 else {
127                     if (parameterCount != explicitArgs.length) {
128                         continue;
129                     }
130                     argsHolder = new ArgumentsHolder(explicitArgs);
131                 }
132 
133                 int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
134                         argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
135                 if (typeDiffWeight < minTypeDiffWeight) {
136                     constructorToUse = candidate;
137                     argsHolderToUse = argsHolder;
138                     argsToUse = argsHolder.arguments;
139                     minTypeDiffWeight = typeDiffWeight;
140                     ambiguousConstructors = null;
141                 }
142                 else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
143                     if (ambiguousConstructors == null) {
144                         ambiguousConstructors = new LinkedHashSet<>();
145                         ambiguousConstructors.add(constructorToUse);
146                     }
147                     ambiguousConstructors.add(candidate);
148                 }
149             }
150 
151             // 没有找到构造器或者找到两个出现歧义的都会抛异常
152             if (constructorToUse == null) {
153                 if (causes != null) {
154                     UnsatisfiedDependencyException ex = causes.removeLast();
155                     for (Exception cause : causes) {
156                         this.beanFactory.onSuppressedException(cause);
157                     }
158                     throw ex;
159                 }
160                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
161                         "Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
162                         "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
163             }
164             else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
165                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
166                         "Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
167                         "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
168                         ambiguousConstructors);
169             }
170 
171             if (explicitArgs == null && argsHolderToUse != null) {
172                 argsHolderToUse.storeCache(mbd, constructorToUse);
173             }
174         }
175 
176         // 匹配到合适的构造器了,进行创建bean
177         Assert.state(argsToUse != null, "Unresolved constructor arguments");
178         bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
179         return bw;
180     }
View Code

东西多不多= =看麻了,他要解析你的类有多少个构造方法,每个构造方法有哪些参数,参数的类型以及你参数的值,解析出来,进行一个匹配的过程,只有一个默认的构造或者匹配到一个合适的构造方法就会调用instantiate,进行创建并返回。

  • 创建返回值BeanWrapperImpl 对象
  • 判断是不是只有一个默认构造方法,是的话就调用默认构造方法创建并返回
  • 获取构造方法,并排序
  • 遍历每个构造方法,进行参数解析 参数值解析,筛选出一个合适的构造方法
  • 缓存这些解析信息
  • 创建bean 
  • 将bean放进BeanWrapperImpl 对象并返回

Spring基本上每个基础的类的信息都会有缓存,变量很多,自己看的时候可以创建几个bean,多搞几个构造方法结合着看。

2.3 instantiateBean-通过默认构造方法创建 bean 实例

这个是使用默认的构造方法去创建bean,他最终也会调到instantiate方法,所谓殊途同归嘛,那么我们来看看:

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            // 安全检查,咱也不是很懂,可以略过
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(
                        (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
                        getAccessControlContext());
            }
            else {
                /*
                 * 这里又出现一个初始化策略。
                 * 如果 bean 的配置信息中包含 lookup-method 和 replace-method,则通过 CGLIB 创建 bean 对象
                 */
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
            }
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
        // 检测 bean 配置中是否配置了 lookup-method 或 replace-method,若配置了,则需使用 CGLIB 构建 bean 对象
        if (!bd.hasMethodOverrides()) {
            Constructor<?> constructorToUse;
            synchronized (bd.constructorArgumentLock) {
                constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {
                    final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                        if (System.getSecurityManager() != null) {
                            constructorToUse = AccessController.doPrivileged(
                                    (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                        }
                        else {
                            // 获取默认构造方法
                            constructorToUse = clazz.getDeclaredConstructor();
                        }
                        bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                    }
                    catch (Throwable ex) {
                        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
                }
            }
            // 通过无参构造方法创建 bean 对象
            return BeanUtils.instantiateClass(constructorToUse);
        }
        else {
            // 使用 GCLIG 创建 bean 对象
            return instantiateWithMethodInjection(bd, beanName, owner);
        }
    }
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
        Assert.notNull(ctor, "Constructor must not be null");
        try {
            // 设置构造方法为可访问
            ReflectionUtils.makeAccessible(ctor);
            // Kotlin是个啥= = 有个Kotlin的判断
            if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
                return KotlinDelegate.instantiateClass(ctor, args);
            }
            else {
                Class<?>[] parameterTypes = ctor.getParameterTypes();
                Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
                Object[] argsWithDefaultValues = new Object[args.length];
                for (int i = 0 ; i < args.length; i++) {
                    if (args[i] == null) {
                        Class<?> parameterType = parameterTypes[i];
                        argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
                    }
                    else {
                        argsWithDefaultValues[i] = args[i];
                    }
                }
                // 通过反射创建 bean 实例,这里的 args 是一个没有元素的空数组
                return ctor.newInstance(argsWithDefaultValues);
            }
        }
        catch (InstantiationException ex) {
            throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
        }
        catch (IllegalAccessException ex) {
            throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
        }
        catch (IllegalArgumentException ex) {
            throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
        }
        catch (InvocationTargetException ex) {
            throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
        }
    }

铁子们,这bean创建的过程真是不容小觑,分的情况很多,创建对象就是根据构造方法来创建,构造方法Spring又做了增强比如lookup,Spring又要根据增强和构造方法根据策略生成自己的代理对象出来,一层套一层其中还涉及解析缓存,结果缓存,真的复杂,休息一下。

2.4 obtainFromSupplier-根据定义信息中的Supplier创建

supplier其实也就是一个函数接口,类似FactoryBean都是直接提供对象出来,源码如下:

protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
        Object instance;

        String outerBean = this.currentlyCreatedBean.get();
        this.currentlyCreatedBean.set(beanName);
        try {
            // 根据你提供的Supplier其实也就是方法 返回
            instance = instanceSupplier.get();
        }
        finally {
            if (outerBean != null) {
                this.currentlyCreatedBean.set(outerBean);
            }
            else {
                this.currentlyCreatedBean.remove();
            }
        }

        if (instance == null) {
            instance = new NullBean();
        }
        BeanWrapper bw = new BeanWrapperImpl(instance);
        initBeanWrapper(bw);
        return bw;
    }

2.4 resolveBeforeInstantiation-勾子处理器InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。

解释两个单词Instantiation 这个是实例化,表示对象还没创建出来,Initialization这个是初始化,对象已经创建完,只是还没初始化属性也就是BeanPostProcessor的前后处理都是针对初始化的,InstantiationAwareBeanPostProcessor自身的方法,是针对创建的过程,直接做干预。

FactoryBean就不说了,它跟构造方法有点像,从方法里边去挑选,去解析筛选。

3 小结

小结就是累了,你仔细去看看构造方法创建bean,那家伙简直调的太多了,有哪里不对的地方,也请评论指出来,互相学习。

posted @ 2023-02-16 08:18  酷酷-  阅读(75)  评论(0编辑  收藏  举报