doCreateBean - createBeanInstance

接着前面, 看完构造函数前的后置处理器, 就到 doCreateBean 方法了. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args...

接着前面, 看完构造函数前的后置处理器, 就到 doCreateBean 方法了.

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        /**
         * 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。
         * createBeanInstance中包含三种创建 bean 实例的方式:
         *   1. 通过工厂方法创建 bean 实例
         *   2. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例
         *   3. 通过无参构造方法方法创建 bean 实例
         *
         * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB 增强 bean 实例。
         */
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                //调用属性合并后置处理器, 进行属性合并
                //这里会进行 一些注解 的扫描
                //CommonAnnotationBeanPostProcessor -> @PostConstruct @PreDestroy @Resource
                //AutowiredAnnotationBeanPostProcessor -> @Autowired @Value
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        //这里创建了一个匿名的 ObjectFactory 实现类, 他是一个工厂, 可以用来获取对象
        //addSingletonFactory中, 将这个工厂放到 singletonFactories 中去了. singletonFactories 是spring的三级缓存
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        //设置属性,非常重要
        populateBean(beanName, mbd, instanceWrapper);
        //执行后置处理器,aop就是在这里完成的处理
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

1. 第一次进来时, 对象肯定是null, 所以会进行一次反射创建过程.

2. 然后会执行属性合并后置处理器, 在这个后置处理器中, 会进行一些属性合并和一些注解的扫描

3. 合并完属性之后, 就要进行属性的注入了, 比如 @Autowired 注入

4. 开始初始化过程, 调用 一些初始化方法

整个过程是非常符合逻辑的.

没有对象则创建对象, 有了对象之后, 看看有那些属性需要注入, 当属性都准备妥当时, 执行初始化方法, 比如对这些属性做一些什么操作或者通过这些属性, 拿到一些什么东西等等.

createBeanInstance

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    //检测一个类的访问权限, spring默认情况下对于非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 对象
    // 这种是在 xml 中配置 bean 的 factory-method
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // Shortcut when re-creating the same bean...
    /**
     * 从spring的原始注释可以知道这个是一个Shortcut,什么意思呢?
     * 当多次构建同一个 bean 时,可以使用这个Shortcut,
     * 也就是说不在需要次推断应该使用哪种方式构造bean
     *  比如在多次构建同一个prototype类型的 bean 时,就可以走此处的shortcut
     * 这里的 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) {
            // 通过构造方法自动装配的方式构造 bean 对象
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            //通过默认的无参构造方法进行
            return instantiateBean(beanName, mbd);
        }
    }

    // Candidate constructors for autowiring?
    // 由后置处理器决定返回哪些构造方法, 当出现多个构造函数时, 返回为 null
    // 这里的后置处理器是 SmartInstantiationAwareBeanPostProcessor, 调用其 determineCandidateConstructors 方法
    // 具体处理在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 中进行
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        //需要对构造函数的参数进行注入, 可以通过 ImportBeanDefinitionRegistrar 来修改 bd 的自动装配模式:
        // AnnotatedGenericBeanDefinition bd = new AnnotatedGenericBeanDefinition(IndexDao1.class);
        // bd.setAutowireMode(AnnotatedGenericBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        // registry.registerBeanDefinition("indexDao1", bd);
        return autowireConstructor(beanName, mbd, ctors, args);
    }

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

    // No special handling: simply use no-arg constructor.
    //使用默认的无参构造方法进行初始化
    return instantiateBean(beanName, mbd);
}

我通常的使用习惯是, 使用 @Autowired 来进行注入操作(虽然有些人提倡通过构造注入的方式). 

按照我这个习惯, 构造函数是默认构造函数, actors 返回来是null , 所以不会走 autowireConstructor 来创建,

而是会走到 最下面, 在 instantiateBean() 中, 通过无参构造函数反射创建对象. 

这种创建对象的方式, 是最简单的. 同时能避免一个 构造函数造成的相互依赖问题, 这个问题是无解的.

determineConstructorsFromBeanPostProcessors

这里会调用构造函数的后置处理器, 来进行构造函数的选择

@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
        throws BeansException {

    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
                if (ctors != null) {
                    return ctors;
                }
            }
        }
    }
    return null;
}

这个后置处理器, 只能放在下一篇来看了, 这里先不管了. 其中的道道, 还是蛮多的.

instantiateBean

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                    getInstantiationStrategy().instantiate(mbd, beanName, parent),
                    getAccessControlContext());
        }
        else {
            //getInstantiationStrategy()得到类的实例化策略
            //得到一个反射的实例化策略 : SimpleInstantiationStrategy
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

这里就是实例化 bean 的地方了, 

实例化之后, 还会设置一些属性转换器

SimpleInstantiationStrategy.instantiate

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
    //检测 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);
                }
            }
        }
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // Must generate CGLIB subclass.
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

BeanUtils.instantiateClass 就是反射创建对象的方法.

这里虽说有创建 cglib 的方法, 但是里面只是抛出了异常

throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");

lookup-method 和 replace-method , 我基本都只是在学习的时候, 才去使用过, 如果想要用的话, 需要改变这里的实例化策略, 也就是不用 SimpleInstantiationStrategy .

initBeanWrapper

org.springframework.beans.factory.support.AbstractBeanFactory#initBeanWrapper

protected void initBeanWrapper(BeanWrapper bw) {
    bw.setConversionService(getConversionService());
    registerCustomEditors(bw);
}

ConversionService 是做属性转换的

registerCustomEditors 其实就是注册一些属性转换器. 如:

org.springframework.beans.support.ResourceEditorRegistrar#registerCustomEditors

@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
    ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
    doRegisterEditor(registry, Resource.class, baseEditor);
    doRegisterEditor(registry, ContextResource.class, baseEditor);
    doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
    doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
    doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
    doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
    doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
    doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));

    ClassLoader classLoader = this.resourceLoader.getClassLoader();
    doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
    doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
    doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));

    if (this.resourceLoader instanceof ResourcePatternResolver) {
        doRegisterEditor(registry, Resource[].class,
                new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
    }
}

autowireConstructor

想进这个方法, 其实也简单. 方法有很多种, 其中一种最简单的, 就是只放一个有参构造方法就行了.

在这里, spring会根据自己的规则, 来进行 构造函数的选择. 其选择有限级为:

1. 优先按照访问权限, public 放在前面

2. 然后按照参数个数, 参数多的放在前面.

1. public IndexDao(Object o1, Object o2, Object o3)
2. public IndexDao(Object o1, Object o2)
3. public IndexDao(Object o1)
4. protected IndexDao(Integer i, Object o1, Object o2, Object o3)
5. protected IndexDao(Integer i, Object o1, Object o2)
6. protected IndexDao(Integer i, Object o1)

具体逻辑就不看了, 大致是这么个效果.

当选择好后, 就回进行创建工作. 当碰到构造参数时, 会去从容器中 获取/创建 对象

  • 发表于 2020-07-27 21:41
  • 阅读 ( 75 )
  • 分类:网络文章

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除