美文网首页Spring
Spring bean实例化

Spring bean实例化

作者: lesline | 来源:发表于2020-07-28 12:26 被阅读0次

    问题一:何时生成代理对象,尤其是事务的代理对象?
    在两个地方可能生成代理对象:
    一:InstantiationAwareBeanPostProcessor. postProcessBeforeInstantiation
    二:BeanPostProcessor.postProcessAfterInitialization

    生成事务的代理对象执行点:
    (1)在InfrastructureAdvisorAutoProxyCreator.postProcessAfterInitialization方法执行
    (2)SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference执行

    问题二:循环依赖解决?
    为何要三级缓存,而不是二级缓存?
    好处:可扩展,修改提前暴露的对象
    (把 aop 代理对象提前暴露出去,如果此时不暴露,循环依赖时,A 引用的对象不是B 的代理对象)

    实现:三级缓存中存放的为ObjectFactory对象:singletonFactories,当循环依赖时获取缓存对象时,会执行工厂方法
    ObjectFactory.getObject()-------->
    SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
    进而获取AOP代理对象。

    实现过程

    三级缓存.png

    SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法作用:
    当存在循环依赖时,通过该回调方法获取AOP代理对象
    (正常是在InfrastructureAdvisorAutoProxyCreator.postProcessAfterInitialization方法中生成代理对象的)。

    具体过程

    1. 实例化对象后会放三级缓存
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
      注意:放入缓存的是一个ObjectFactory实现,只有在循环依赖时,第二个对象获取第一个对象时,会执行ObjectFactory.getObject()方法实现(即getEarlyBeanReference)

    获取缓存

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
    

    AbstractAutowireCapableBeanFactory#getEarlyBeanReference

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }
    
    

    AbstractAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor的子类,
    实现了getEarlyBeanReference用于生成 aop 代理对象的

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            this.earlyProxyReferences.add(cacheKey);
        }
        return wrapIfNecessary(bean, beanName, cacheKey);
    }
    

    ::wrapIfNecessary方法时生成 AOP代理对象::

    1. 正常生成 aop 代理对象是在postProcessAfterInitialization方法后,
      AbstractAutoProxyCreator#postProcessAfterInitialization实现
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
    

    ::postProcessAfterInitialization 中也使用了 wrapIfNecessary::
    ::不过如果由于在赋值时,为了解决循环依赖已经生成过AOP代理对象,这时不再生成代理::

    一文告诉你Spring是如何利用三级缓存巧妙解决Bean的循环依赖问题的
    Spring源码解析(十二)Spring扩展接口SmartInstantiationAwareBeanPostProcessor

    BeanFactory

    通过源代码看看创建一个Bean实例的具体执行流程:
    [image:A568E489-2D7C-4E9B-9F0B-E1078E700F57-1306-000001E35047C75A/E453601C-514D-4406-9623-ACAB4F899BBD.png]

    1. bean的实例化通过BeanFactory接口实现:DefaultListableBeanFactory,XmlBeanFactory,ApplicationContext 等具体的容器都是实现了BeanFactory,再在其基础之上附加了其他的功能。
    2. AbstractApplicationContext内部使用DefaultListableBeanFactory,且DefaultListableBeanFactory继承AbstractAutowireCapableBeanFactory,因此我们此处分析AbstractAutowireCapableBeanFactory即可。
    3. AbstractAutowireCapableBeanFactory的方法populateBean是主要实现,用于给bean实例填充数据

    Spring创建Bean的流程

    首先需要了解是Spring它创建Bean的流程,我把它的大致调用栈绘图如下:

    Spring创建Bean的流程.png

    对Bean的创建最为核心三个方法解释如下:
    createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象
    populateBean:填充属性,这一步主要是对bean的依赖属性进行注入(@Autowired)
    initializeBean:回到一些形如initMethod、InitializingBean等方法
    一文告诉你Spring是如何利用三级缓存巧妙解决Bean的循环依赖问题

    BeanFactory中bean的生命周期

    当请求getBean时,即实例化bean对象。ApplicationContext是在refresh()方法里立即实例化了所有的bean。

    BeanFactory中bean的生命周期.png

    主要分为三阶段

    1. 实例化,创建Bean的过程,InstantiationAwareBeanPostProcessor作用于此
    2. 填充数据
    3. 初始化,BeanPostProcessor作用于此

    阶段一:实例化

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean()
    此方法为核心方法,用于创建bean实例,填充bean属性,并执行后置方法

    /**
     * Central method of this class: creates a bean instance,
     * populates the bean instance, applies post-processors, etc.
     * @see #doCreateBean
     */
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
    
      //此处为特殊逻辑,如果有InstantiationAwareBeanPostProcessor实现生成代理对象,则直接返回,不会调下面的方法
        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        //创建bean实例,调用populateBean填充属性
        try {
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
    }
    
    

    resolveBeforeInstantiation 的功能为:
    如果有InstantiationAwareBeanPostProcessor实现的postProcessBeforeInstantiation方法生成代理对象,则直接返回,不会调下面的方法

    @Nullable
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                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;
    }
    

    注意:实例化之前执行InstantiationAwareBeanPostProcessor. postProcessBeforeInstantiation方法,当经过前置处理之后,返回的结果若不为空,那么会直接略过后续的Bean的创建而直接返回结果
    ::原因:resolveBeforeInstantiation只是针对有自定义的targetsource,因为自定义的targetsource不是spring的bean那么肯定不需要进行后续的一系列的实例化初始化。所以可以在resolveBeforeInstantiation直接进行proxy::

    Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProcessor解析
    Spring之InstantiationAwareBeanPostProcessor接口介绍 - 云+社区 - 腾讯云
    Spring Aop之Target Source详解Java爱宝贝丶的博客-CSDN博客

    阶段二:填充实例-populateBean实现

    位于:AbstractAutowireCapableBeanFactory#populateBean

    主要功能:

    1. 把Autowired注解的属性注入到实例中
    2. 执行实现了InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation方法修改实例

    执行流程。如下:

    • 获取属性列表 pvs
    • 在属性被填充到 bean 前,应用后置处理自定义属性填充
    • 根据名称或类型解析相关依赖
    • 再次应用后置处理,用于动态修改属性列表 pvs 的内容
    • 将属性应用到 bean 对象中
      注意第3步,也就是根据名称或类型解析相关依赖(autowire)。该逻辑只会解析依赖,并不会将解析出的依赖立即注入到 bean 对象中。所有的属性值是在 applyPropertyValues 方法中统一被注入到 bean 对象中的。
      Spring IOC 容器源码分析 - 填充属性到 bean 原始对象_慕课手记
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        // 获取属性列表
        PropertyValues pvs = mbd.getPropertyValues();
    
        if (bw == null) {
            if (!pvs.isEmpty()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                return;
            }
        }
    
        boolean continueWithPropertyPopulation = true;
        /*
         * 在属性被填充前,给 InstantiationAwareBeanPostProcessor 类型的后置处理器一个修改 
         * bean 状态的机会。关于这段后置引用,官方的解释是:让用户可以自定义属性注入。比如用户实现一
         * 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过 
         * postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。当然,如果无
         * 特殊需求,直接使用配置中的信息注入即可。另外,Spring 并不建议大家直接实现 
         * InstantiationAwareBeanPostProcessor 接口,如果想实现这种类型的后置处理器,更建议
         * 通过继承 InstantiationAwareBeanPostProcessorAdapter 抽象类实现自定义后置处理器。
         */
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }
    
        /* 
         * 如果上面设置 continueWithPropertyPopulation = false,表明用户可能已经自己填充了
         * bean 的属性,不需要 Spring 帮忙填充了。此时直接返回即可
         */
        if (!continueWithPropertyPopulation) {
            return;
        }
    
        // 根据名称或类型注入依赖
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    
            // 通过属性名称注入依赖
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
    
            // 通过属性类型注入依赖
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
    
            pvs = newPvs;
        }
    
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
        /*
         * 这里又是一种后置处理,用于在 Spring 填充属性到 bean 对象前,对属性的值进行相应的处理,
         * 比如可以修改某些属性的值。这时注入到 bean 中的值就不是配置文件中的内容了,
         * 而是经过后置处理器修改后的内容
         */ 
        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        // 对属性进行后置处理
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
    
        // 应用属性值到 bean 对象中
        applyPropertyValues(beanName, mbd, bw, pvs);
    
    

    阶段三:初始化实例

    初始化过程主要包含以下几个过程:

    1. 执行BeanNameAware, BeanClassLoaderAware, BeanFactoryAware 接口实现
    2. 执行BeanPostProcessor.postProcessAfterInitialization:
    3. 执行InitializingBean接口的中afterPropertiesSet()方法(如果该实例实现)
    4. 执行实例init method
    5. 执行BeanPostProcessor.postProcessAfterInitialization
    
    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    
      invokeAwareMethods(beanName, bean);
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
    
        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
    
        return wrappedBean;
    }
    

    相关文章

      网友评论

        本文标题:Spring bean实例化

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