美文网首页
Spring源码(六)-创建Bean流程-createBean

Spring源码(六)-创建Bean流程-createBean

作者: 程序员小杰 | 来源:发表于2021-12-23 20:15 被阅读0次

    createBean 方法总体可以分为四个小方法:

    • resolveBeanClass:加载 Class 对象
    • prepareMethodOverrides:对通过 XML 定义的 bean 中的lookup-methodreplace-method属性进行预处理
    • resolveBeforeInstantiation:实例化前应用后处理器
    • doCreateBean:创建 Bean

    接下来就一个一个来看吧!

    resolveBeanClass

    首先调试进入AbstractAutowireCapableBeanFactory类的createBean

        @Override
        protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {
    
            if (logger.isTraceEnabled()) {
                logger.trace("Creating instance of bean '" + beanName + "'");
            }
            RootBeanDefinition mbdToUse = mbd;
    
            // 使用类加载器根据 class 或者根据 className 来加载 Class
            Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
            if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
            }
          //省略代码...
    }
    

    进入AbstractBeanFactory类中的resolveBeanClass方法,注意typesToMatch的类型可能为FactoryBean.classtypesToMatch是一个可变参数。自己再DeBug的时候可以找找resolveBeanClass方法在哪些地方被调用。

    @Nullable
        protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
                throws CannotLoadBeanClassException {
            //BeanDefintion是在扫描的时候创建的,
            //但是AbstractBeanDefinition中存在一个beanClass属性
            try {
                // 如果beanClass是Class,就直接返回beanClass
                if (mbd.hasBeanClass()) {
                    return mbd.getBeanClass();
                }
                //忽略
                if (System.getSecurityManager() != null) {
                    return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
                        doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
                }
                else {
                    // 加载AbstractBeanDefinition中beanClass中所指定的类名对应的类
                    return doResolveBeanClass(mbd, typesToMatch);
                }
            }
            catch (PrivilegedActionException pae) {
                ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
                throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
            }
            catch (ClassNotFoundException ex) {
                throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
            }
            catch (LinkageError err) {
                throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
            }
        }
    

    进入 AbstractBeanFactory类中的doResolveBeanClass方法

    @Nullable
        private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
                throws ClassNotFoundException {
            // 拿到类加载器
            ClassLoader beanClassLoader = getBeanClassLoader();
            ClassLoader dynamicLoader = beanClassLoader;
            boolean freshResolve = false;
    
            if (!ObjectUtils.isEmpty(typesToMatch)) {
                ClassLoader tempClassLoader = getTempClassLoader();
                if (tempClassLoader != null) {
                    dynamicLoader = tempClassLoader;
                    freshResolve = true;
                    if (tempClassLoader instanceof DecoratingClassLoader) {
                        DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                        for (Class<?> typeToMatch : typesToMatch) {
                            dcl.excludeClass(typeToMatch.getName());
                        }
                    }
                }
            }
    
            // 获取BeanDefinition中所指定的beanClass属性的值,
            String className = mbd.getBeanClassName(); // 字符串 或者 #{xxx}
            if (className != null) {
                // className可以是Spring EL表达式,所以需要解析
                Object evaluated = evaluateBeanDefinitionString(className, mbd);
                // 如果 className 是Spring EL表达式,className 与 evaluated 会不相等的
                if (!className.equals(evaluated)) {
                    // evaluated 类型是Class 直接返回
                    if (evaluated instanceof Class) {
                        return (Class<?>) evaluated;
                    }
                    // evaluated 类型是String 将 freshResolve 的值设置为 true
                    else if (evaluated instanceof String) {
                        className = (String) evaluated;
                        freshResolve = true;
                    }
                    else {
                        throw new IllegalStateException("Invalid class name expression result: " + evaluated);
                    }
                }
                if (freshResolve) {
                    if (dynamicLoader != null) {
                        try {
                            // 使用类加载器加载类
                            return dynamicLoader.loadClass(className);
                        }
                        catch (ClassNotFoundException ex) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
                            }
                        }
                    }
                    // 反射工具类加载Class对象
                    return ClassUtils.forName(className, dynamicLoader);
                }
            }
    
            // 反射工具类加载Class对象
            return mbd.resolveBeanClass(beanClassLoader);
        }
    

    resolveBeanClass 方法就是通过来判断 AbstractBeanDefinition 类中的 beanClass 属性,如果是 Class 就直接返回,如果不是就获取 beanClass 属性的值并将它转换为 Stirng 类型,然后对 className 做表达式解析。最后通过dynamicLoader.loadClass(className)加载 Class 对象,或者通过ClassUtils.forName(className, classLoader)加载 Class 对象。

    prepareMethodOverrides

    对通过XML定义的bean中的lookup-method和replace-method属性进行预处理

        try {
                // 对通过XML定义的bean中的lookup-method和replace-method方法进行预处理
                // 对于@Lookup注解标注的方法不在这里进行处理
                mbdToUse.prepareMethodOverrides();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                        beanName, "Validation of method overrides failed", ex);
            }
    

    进入AbstractBeanDefinition类的prepareMethodOverrides方法

    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
            // Check that lookup methods exist and determine their overloaded status.
            //检查是否存在查找方法,并确定其重载状态。
            if (hasMethodOverrides()) {
                getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
            }
        }
    

    进入AbstractBeanDefinition类的prepareMethodOverride方法

    protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
            // 获取对应本类、父类、父接口中对应方法的个数
            int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
            if (count == 0) {
                throw new BeanDefinitionValidationException(
                        "Invalid method override: no method with name '" + mo.getMethodName() +
                        "' on class [" + getBeanClassName() + "]");
            }
            else if (count == 1) {
                //标记 overloaded 暂未被被盖 避免参数类型检查的开销
                mo.setOverloaded(false);
            }
        }
    

    该方法主要针对lookup-methodreplace-method做预处理,现在这两个属性用得比较少了。如果对这两个属性有兴趣,可以在 Spring 的官网进行查看: 点我前往
    也可以移步前往: Spring源码(二—2)-lookup-method、replaced-method元素

    resolveBeforeInstantiation

        try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                // 1、实例化前
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);  // 对象
                if (bean != null) {
                    return bean;
                }
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                        "BeanPostProcessor before instantiation of bean failed", ex);
            }
    

    注意上面方法中有个if判断块,当经过前置处理后返回的结果如果不为空,那么会直接略过后续 bean 的创建而直接返回结果。当前 Bean 的创建流程结束,不会再往下执行 doCreateBean 函数。

    进入 AbstractAutowireCapableBeanFactory类的resolveBeforeInstantiation方法

    @Nullable
        protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
            Object bean = null;
            // beforeInstantiationResolved的值只会为null或true
            if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
                if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                    // 返回 Class 对象
                    Class<?> targetType = determineTargetType(beanName, mbd);
                    if (targetType != null) {
                        // 实例化前
                        bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                        if (bean != null) {
                            //初始化后
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                        }
                    }
                }
                mbd.beforeInstantiationResolved = (bean != null);
            }
            return bean;
        }
    

    然后进入 AbstractAutowireCapableBeanFactory类的determineTargetType方法,该方法就是将 Class 对象加载出来。

        @Nullable
        protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
            // 获取resolvedTargetType属性,也相当于缓存,
            Class<?> targetType = mbd.getTargetType();
            if (targetType == null) {
                // 如果BeanDefinition中设置了factoryMethodName,那么就通过factoryMethodName来判断类型,
                // 否则获取AbstractBeanDefinition中的beanClass
                targetType = (mbd.getFactoryMethodName() != null ?
                        getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
                        resolveBeanClass(mbd, beanName, typesToMatch));
                if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
                    // 将解析出来的类型记录到resolvedTargetType中
                    mbd.resolvedTargetType = targetType;
                }
            }
            
            return targetType;
        }
    

    AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsBeforeInstantiation实例化前方法

        @Nullable
        protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 执行 postProcessBeforeInstantiation 方法,也就是 实例化前
                    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                    if (result != null) {
                        return result;
                    }
                }
            }
            return null;
        }
    

    注意:上述方法的方法名 applyBeanPostProcessors BeforeInstantiationBeforeInstantiation实例化前。首先获得所有的 BeanPostProcessor ,然后循环遍历判断是否实现了InstantiationAwareBeanPostProcessor,然后执行 postProcessBeforeInstantiation实例化前方法。如果 postProcessBeforeInstantiation方法返回了对象,也就是不返回 null,就执行 applyBeanPostProcessorsAfterInitialization初始化后方法。

    AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsAfterInitialization初始化后方法

    @Override
        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {
    
            Object result = existingBean;
            for (BeanPostProcessor processor : getBeanPostProcessors()) {
                // 执行postProcessAfterInitialization方法,也就是初始化后
                Object current = processor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }
    

    也要注意该方法的方法名 applyBeanPostProcessorsAfterInitializationAfterInitialization初始化后。获取到所有的 BeanPostProcessor,然后循环每个BeanPostProcessorpostProcessAfterInitialization初始化后方法。如果postProcessAfterInitialization初始化后方法的返回值为 null就直接结束循环,进行返回。比如我有三个 BeanPostProcessor ,A、B、C,在执行A BeanPostProcessor 的时候,A的postProcessAfterInitialization方法返回了null,B、C两个BeanPostProcessor 不会再执行。AOP 也在此进行执行。

    如果对于 BeanPostProcessor不熟悉的伙伴可以移步前往:Spring源码-BeanPostProcessor

    doCreateBean

    程序执行了 resolveBeforeInstantiation函数之后,如果返回的结果为 null,就需要执行 doCreateBean函数进行创建 Bean。

    try {
                // 创建bean   Spring自带的创建bean的方法
                Object beanInstance = doCreateBean(beanName, mbdToUse, args);
                if (logger.isTraceEnabled()) {
                    logger.trace("Finished creating instance of bean '" + beanName + "'");
                }
                return beanInstance;
            }
    

    doCreateBean 函数的篇幅太长,将拆分几篇文章进行阅读。

    • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。

    相关文章

      网友评论

          本文标题:Spring源码(六)-创建Bean流程-createBean

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