Spring IOC 容器源码分析 - getBean调用方法解析(三) -- 实例化 Bean 对象

1. createBeanInstance


    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 解析 bean ,将 bean 类名解析为 class 引用
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        /*
         * 检测类的访问权限。默认情况下,对于非 public 的类,是允许访问的。
         * 若禁止访问,这里会抛出异常
         */
        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());
        }

        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }

        /*
          *  <bean id="dynamicStu" factory-bean="stuFactory" factory-method="getDynamicStu">
         * 如果工厂方法不为空,则通过工厂方法构建 bean 对象
         */
        if (mbd.getFactoryMethodName() != null) {
            // 使用 FactoryBean 的 factory-method 来创建,支持静态工厂和实例工厂
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        /*
         * 当多次构建同一个 bean 时,可以使用此处的快捷路径,即无需再次推断应该使用哪种方式构造实例,
         * 以提高效率。比如在多次构建同一个 prototype 类型的 bean 时,就可以走此处的捷径。
         * 这里的 resolved 和 mbd.constructorArgumentsResolved 将会在 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) {
                //  autowire 自动注入,调用构造函数自动注入
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 通过“默认构造方法”的方式构造 bean 对象
                return instantiateBean(beanName, mbd);
            }
        }

        // 确定解析的构造函数
        // 主要是检查已经注册的 SmartInstantiationAwareBeanPostProcessor
        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);
        }

        // Preferred constructors for default construction?
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            return autowireConstructor(beanName, mbd, ctors, null);
        }

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

2.autowireConstructor

  这个初始化方法,我们可以简单理解为是带有参数的构造方法,来初始化 Bean 对象


public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
            @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

        // 创建 BeanWrapperImpl 对象
        BeanWrapperImpl bw = new BeanWrapperImpl();
        this.beanFactory.initBeanWrapper(bw);

        Constructor<?> constructorToUse = null;// 构造函数
        ArgumentsHolder argsHolderToUse = null;// 构造参数
        Object[] argsToUse = null;// 构造参数

        // 确定构造参数
        // 如果 getBean() 已经传递,则直接使用
        if (explicitArgs != null) {
            argsToUse = explicitArgs;
        }
        else {
            // 尝试从缓存中获取
            Object[] argsToResolve = null;
            synchronized (mbd.constructorArgumentLock) {
                // 缓存中的构造函数或者工厂方法
                constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse != null && mbd.constructorArgumentsResolved) {
                    // 获取已解析的构造方法参数列表
                    argsToUse = mbd.resolvedConstructorArguments;
                    if (argsToUse == null) {
                        // 若 argsToUse 为空,则获取未解析的构造方法参数列表
                        argsToResolve = mbd.preparedConstructorArguments;
                    }
                }
            }
            // 缓存中存在,则解析存储在 BeanDefinition 中的参数
            // 如给定方法的构造函数 A(int ,int ),则通过此方法后就会把配置文件中的("1","1")转换为 (1,1)
            // 缓存中的值可能是原始值也有可能是最终值
            if (argsToResolve != null) {
                // 解析参数列表
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
            }
        }
        // 没有缓存,则尝试从配置文件中获取参数
        if (constructorToUse == null || argsToUse == null) {
            // 如果 chosenCtors 未传入,则获取构造方法们
            Constructor<?>[] candidates = chosenCtors;
            if (candidates == null) {
                Class<?> beanClass = mbd.getBeanClass();
                try {
                    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);
                }
            }

            if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
                Constructor<?> uniqueCandidate = candidates[0];
                if (uniqueCandidate.getParameterCount() == 0) {
                    synchronized (mbd.constructorArgumentLock) {
                        mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                        mbd.constructorArgumentsResolved = true;
                        mbd.resolvedConstructorArguments = EMPTY_ARGS;
                    }
                    bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
                    return bw;
                }
            }

            // 是否需要解析构造器
            boolean autowiring = (chosenCtors != null ||
                    mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
            // 用于承载解析后的构造函数参数的值
            ConstructorArgumentValues resolvedValues = null;

            int minNrOfArgs;
            if (explicitArgs != null) {
                minNrOfArgs = explicitArgs.length;
            }
            else {
                // 从 BeanDefinition 中获取构造参数,也就是从配置文件中提取构造参数
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                resolvedValues = new ConstructorArgumentValues();
                /*
                 * 确定构造方法参数数量,比如下面的配置:
                 *     <bean id="persion" class="xyz.coolblog.autowire.Person">
                 *         <constructor-arg index="0" value="xiaoming"/>
                 *         <constructor-arg index="1" value="1"/>
                 *         <constructor-arg index="2" value="man"/>
                 *     </bean>
                 *
                 * 此时 minNrOfArgs = maxIndex + 1 = 2 + 1 = 3,除了计算 minNrOfArgs,
                 * 下面的方法还会将 cargs 中的参数数据转存到 resolvedValues 中
                 */
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
            }
            // 对构造函数进行排序处理
            // public 构造函数优先参数数量降序,非public 构造函数参数数量降序
            AutowireUtils.sortConstructors(candidates);
            // 最小参数类型权重
            int minTypeDiffWeight = Integer.MAX_VALUE;
            Set<Constructor<?>> ambiguousConstructors = null;
            LinkedList<UnsatisfiedDependencyException> causes = null;
            // 迭代所有构造函数
            for (Constructor<?> candidate : candidates) {
                // 获取该构造函数的参数类型
                Class<?>[] paramTypes = candidate.getParameterTypes();

                /*
                 * 下面的 if 分支的用途是:若匹配到到合适的构造方法了,提前结束 for 循环
                 * constructorToUse != null 这个条件比较好理解,下面分析一下条件 argsToUse.length > paramTypes.length:
                 * 前面说到 AutowireUtils.sortConstructors(candidates) 用于对构造方法进行
                 * 排序,排序规则如下:
                 *   1. 具有 public 访问权限的构造方法排在非 public 构造方法前
                 *   2. 参数数量多的构造方法排在前面
                 *
                 * 假设现在有一组构造方法按照上面的排序规则进行排序,排序结果如下(省略参数名称):
                 *
                 *   1. public Hello(Object, Object, Object)
                 *   2. public Hello(Object, Object)
                 *   3. public Hello(Object)
                 *   4. protected Hello(Integer, Object, Object, Object)
                 *   5. protected Hello(Integer, Object, Object)
                 *   6. protected Hello(Integer, Object)
                 *
                 * argsToUse = [num1, obj2],可以匹配上的构造方法2和构造方法6。由于构造方法2有
                 * 更高的访问权限,所以没理由不选他(尽管后者在参数类型上更加匹配)。由于构造方法3
                 * 参数数量 < argsToUse.length,参数数量上不匹配,也不应该选。所以
                 * argsToUse.length > paramTypes.length 这个条件用途是:在条件
                 * constructorToUse != null 成立的情况下,通过判断参数数量与参数值数量
                 * (argsToUse.length)是否一致,来决定是否提前终止构造方法匹配逻辑。
                 */
                if (constructorToUse != null && argsToUse != 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;
                }
                /*
                 * 构造方法参数数量低于配置的参数数量,则忽略当前构造方法,并重试。比如
                 * argsToUse = [obj1, obj2, obj3, obj4],上面的构造方法列表中,
                 * 构造方法1、2和3显然不是合适选择,忽略之。
                 */
                if (paramTypes.length < minNrOfArgs) {
                    continue;
                }
                // 参数持有者 ArgumentsHolder 对象
                ArgumentsHolder argsHolder;
                if (resolvedValues != null) {
                    try {
                        /*
                         * 判断否则方法是否有 ConstructorProperties 注解,若有,则取注解中的
                         * 值。比如下面的代码:
                         *
                         *  public class Persion {
                         *      private String name;
                         *      private Integer age;
                         *
                         *      @ConstructorProperties(value = {"coolblog", "20"})
                         *      public Persion(String name, Integer age) {
                         *          this.name = name;
                         *          this.age = age;
                         *      }
                         * }
                         */
                        String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                        if (paramNames == null) {
                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                            if (pnd != null) {
                                /*
                                 * 获取构造方法参数名称列表,比如有这样一个构造方法:
                                 *   public Person(String name, int age, String sex)
                                 *
                                 * 调用 getParameterNames 方法返回 paramNames = [name, age, sex]
                                 */
                                paramNames = pnd.getParameterNames(candidate);
                            }
                        }
                        /*
                         * 创建参数值列表,返回 argsHolder 会包含进行类型转换后的参数值,比如下
                         * 面的配置:
                         *
                         *     <bean id="persion" class="xyz.coolblog.autowire.Person">
                         *         <constructor-arg name="name" value="xiaoming"/>
                         *         <constructor-arg name="age" value="1"/>
                         *         <constructor-arg name="sex" value="man"/>
                         *     </bean>
                         *
                         * Person 的成员变量 age 是 Integer 类型的,但由于在 Spring 配置中
                         * 只能配成 String 类型,所以这里要进行类型转换。
                         */
                        argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
                                getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
                    }
                    catch (UnsatisfiedDependencyException ex) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Ignoring constructor [" + candidate + "] of bean ‘" + beanName + "‘: " + ex);
                        }
                        // Swallow and try next constructor.
                        if (causes == null) {
                            causes = new LinkedList<>();
                        }
                        causes.add(ex);
                        continue;
                    }
                }
                else {
                    // Explicit arguments given -> arguments length must match exactly.
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    argsHolder = new ArgumentsHolder(explicitArgs);
                }

                /*
                 * 计算参数值(argsHolder.arguments)每个参数类型与构造方法参数列表
                 * (paramTypes)中参数的类型差异量,差异量越大表明参数类型差异越大。参数类型差异
                 * 越大,表明当前构造方法并不是一个最合适的候选项。引入差异量(typeDiffWeight)
                 * 变量目的:是将候选构造方法的参数列表类型与参数值列表类型的差异进行量化,通过量化
                 * 后的数值筛选出最合适的构造方法。
                 *
                 * isLenientConstructorResolution 判断解析构造函数的时候是否以宽松模式还是严格模式
                 * 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
                 * 宽松模式:使用具有"最接近的模式"进行匹配
                 * typeDiffWeight:类型差异权重
                 */
                int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                        argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                // 如果它代表着当前最接近的匹配则选择其作为构造函数
                if (typeDiffWeight < minTypeDiffWeight) {
                    constructorToUse = candidate;
                    argsHolderToUse = argsHolder;
                    argsToUse = argsHolder.arguments;
                    minTypeDiffWeight = typeDiffWeight;
                    ambiguousConstructors = null;
                }
                /*
                 * 如果两个构造方法与参数值类型列表之间的差异量一致,那么这两个方法都可以作为
                 * 候选项,这个时候就出现歧义了,这里先把有歧义的构造方法放入
                 * ambiguousConstructors 集合中
                 */
                else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
                    if (ambiguousConstructors == null) {
                        ambiguousConstructors = new LinkedHashSet<>();
                        ambiguousConstructors.add(constructorToUse);
                    }
                    ambiguousConstructors.add(candidate);
                }
            }
            // 若上面未能筛选出合适的构造方法,这里将抛出 BeanCreationException 异常
            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)");
            }
            /*
             * 如果 constructorToUse != null,且 ambiguousConstructors 也不为空,表明解析
             * 出了多个的合适的构造方法,此时就出现歧义了。Spring 不会擅自决定使用哪个构造方法,
             * 所以抛出异常。
             */
            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 != null) {
                /*
                 * 缓存相关信息,比如:
                 *   1. 已解析出的构造方法对象 resolvedConstructorOrFactoryMethod
                 *   2. 构造方法参数列表是否已解析标志 constructorArgumentsResolved
                 *   3. 参数值列表 resolvedConstructorArguments 或 preparedConstructorArguments
                 *
                 * 这些信息可用在其他地方,用于进行快捷判断
                 */
                argsHolderToUse.storeCache(mbd, constructorToUse);
            }
        }

        Assert.state(argsToUse != null, "Unresolved constructor arguments");
        bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
        return bw;
    }

  上面的方法逻辑比较复杂,做了不少事情,该方法的核心逻辑是根据参数值类型筛选合适的构造方法。解析出合适的构造方法后,剩下的工作就是构建 bean 对象了,这个工作交给了实例化策略去做。下面罗列一下这个方法的工作流程吧:

  1. 创建 BeanWrapperImpl 对象
  2. 解析构造方法参数,并算出 minNrOfArgs
  3. 获取构造方法列表,并排序
  4. 遍历排序好的构造方法列表,筛选合适的构造方法
    1. 获取构造方法参数列表中每个参数的名称
    2. 再次解析参数,此次解析会将value 属性值进行类型转换,由 String 转为合适的类型。
    3. 计算构造方法参数列表与参数值列表之间的类型差异量,以筛选出更为合适的构造方法
  5. 缓存已筛选出的构造方法以及参数值列表,若再次创建 bean 实例时,可直接使用,无需再次进行筛选
  6. 使用初始化策略创建 bean 对象
  7. 将 bean 对象放入 BeanWrapperImpl 对象中,并返回该对象

3.instantiateBean通过默认构造方法创建对象

    protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            final BeanFactory parent = this;
            // if 条件分支里的一大坨是 Java 安全相关的代码,可以忽略,直接看 else 分支
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                        getInstantiationStrategy().instantiate(mbd, beanName, parent),
                        getAccessControlContext());
            }
            else {
                /*
                 * 调用实例化策略创建实例,默认情况下使用反射创建对象。如果 bean 的配置信息中
                 * 包含 lookup-method 和 replace-method,则通过 CGLIB 创建 bean 对象
                 */
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
            }
            // 创建 BeanWrapperImpl 对象
            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();
                        }
                        // 设置 resolvedConstructorOrFactoryMethod
                        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);
        }
    }

上面就是通过默认构造方法创建 bean 对象的过程,比较简单,就不多说了。最后我们再来看看简单看看通过无参构造方法刚创建 bean 对象的代码(通过 CGLIB 创建 bean 对象的方式就不看了)是怎样的,如下:

    public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
        Assert.notNull(ctor, "Constructor must not be null");
        try {
            // 设置构造方法为可访问
            ReflectionUtils.makeAccessible(ctor);
            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());
        }
    }

  总算看见newInstance

原文地址:https://www.cnblogs.com/w2116o2115/p/12699164.html

时间: 2024-10-05 23:26:46

Spring IOC 容器源码分析 - getBean调用方法解析(三) -- 实例化 Bean 对象的相关文章

Spring IOC 容器源码分析 - 创建单例 bean 的过程

1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去创建,而是从缓存中获取.如果某个 bean 还未实例化,这个时候就无法命中缓存.此时,就要根据 bean 的配置信息去创建这个 bean 了.相较于getBean(String)方法的实现逻辑,创建 bean 的方法createBean(String, RootBeanDefinition, Obj

Spring IOC 容器源码分析 - 余下的初始化工作

1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bean 做最后的初始化工作.相较于之前几篇文章所分析的源码,initializeBean 的源码相对比较简单,大家可以愉快的阅读.好了,其他的不多说了,我们直入主题吧. 2. 源码分析 本章我们来分析一下 initializeBean 方法的源码.在完成分析后,还是像往常一样,把方法的执行流程列出来.好了,看源码

Spring IOC 容器源码分析 - 填充属性到 bean 原始对象

1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反射创建一个原始的 bean 对象,然后再向这个原始的 bean 对象中填充属性.对于填充属性这个过程,简单点来说,JavaBean 的每个属性通常都有 getter/setter 方法,我们可以直接调用 setter 方法将属性值设置进去.当然,这样做还是太简单了,填充属性的过程中还有许多事情要做.

Spring IOC 容器源码分析

前言: Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文并不能让你成为 Spring 专家,不过一定有助于大家理解 Spring 的很多概念,帮助大家排查应用中和 Spring 相关的一些问题. 阅读建议:读者至少需要知道怎么配置 Spring,了解 Spring 中的各种概念,少部分内容我还假设读者使用过 SpringMVC.本文要说的 IOC

Spring IOC 容器源码分析 - 创建原始 bean 对象

1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreateBean方法中的一个重要的调用,即createBeanInstance方法.在本篇文章中,你将看到三种不同的构造 bean 对象的方式.你也会了解到构造 bean 对象的两种策略.如果你对这些内容感兴趣,那么不妨继续往下读.我会在代码进行大量的注解,相信能帮助你理解代码逻辑.好了,其他的就不多说了

Spring Core Container 源码分析三:Spring Beans 初始化流程分析

前言 本文是笔者所著的 Spring Core Container 源码分析系列之一: 本篇文章主要试图梳理出 Spring Beans 的初始化主流程和相关核心代码逻辑: 本文转载自本人的私人博客,伤神的博客: http://www.shangyang.me/2017/04/01/spring-core-container-sourcecode-analysis-beans-instantiating-process/ 本文为作者的原创作品,转载需注明出处: 源码分析环境搭建 参考 Sprin

【Spring源码分析】非懒加载的Bean实例化过程(下篇)

doCreateBean方法 上文[Spring源码分析]非懒加载的Bean实例化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireCapableBeanFactory的doCreateBean方法代码: 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[]

Spring Core Container 源码分析七:注册 Bean Definitions

前言 原本以为,Spring 通过解析 bean 的配置,生成并注册 bean defintions 的过程不太复杂,比较简单,不用单独开辟一篇博文来讲述:但是当在分析前面两个章节有关 @Autowired.@Component.@Service 注解的注入机制的时候,发现,如果没有对有关 bean defintions 的解析和注册机制彻底弄明白,则很难弄清楚 annotation 在 Spring 容器中的底层运行机制:所以,本篇博文作者将试图去弄清楚 Spring 容器内部是如何去解析 b

vlc源码分析之调用live555接收RTSP数据

首先了解RTSP/RTP/RTCP相关概念,尤其是了解RTP协议:RTP与RTCP协议介绍(转载). vlc使用模块加载机制调用live555,调用live555的文件是live555.cpp. 一.几个重要的类 以下向左箭头("<-")为继承关系. 1. RTPInterface RTPInterface是RTPSource的成员变量,其成员函数handleRead会读取网络数据存入BufferedPacket内,该类最终会调到UDP的发送接收函数. Boolean RTPIn