美文网首页
AbstractAutowireCapableBeanFacto

AbstractAutowireCapableBeanFacto

作者: 王侦 | 来源:发表于2022-12-07 07:59 被阅读0次

    1.AbstractAutowireCapableBeanFactory#createBean()主流程

        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;
    
            // Make sure bean class is actually resolved at this point, and
            // clone the bean definition in case of a dynamically resolved Class
            // which cannot be stored in the shared merged bean definition.
            //判断当前mbd中的class是否已经加载到jvm,如果未加载,则使用类加载器将classStr加载到Jvm中,并且返回Class对象
            Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
            //条件一:拿到mbd实例化对象时的真实Class对象。
            //条件二(!mbd.hasBeanClass()):条件成立,说明mbd在resolveBeanClass之前,是没有Class对象的。
            //条件三:成立,说明mbd有ClassName
            if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
            }
    
            // Prepare method overrides.
            try {
                // 对XML标签中定义的lookUp属性进行预处理,如果只能根据名字找到一个就标记为非重载的,这样在后续就不需要去推断到底是哪个方法了,
                // 对于@LookUp注解标注的方法是不需要在这里处理的,AutowiredAnnotationBeanPostProcessor会处理这个注解
                mbdToUse.prepareMethodOverrides();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                        beanName, "Validation of method overrides failed", ex);
            }
    
            try {
                // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                //可以通过后处理器,在这一步返回一个代理实例对象..注意,这里的代理对象不是Spring AOP 逻辑实现的地方。
                //instantiation 实例化不要和init 搞混。
                //后处理器调用点:创建实例之前的一个调用点。
                // 它的另外一个作用就是对AOP提供了支持,在这里会将一些不需要被代理的Bean进行标记
                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);
            }
    
            try {
                //核心方法:创建bean实例对象,并且生命周期的动作大部分都在这里
                Object beanInstance = doCreateBean(beanName, mbdToUse, args);
                if (logger.isTraceEnabled()) {
                    logger.trace("Finished creating instance of bean '" + beanName + "'");
                }
                return beanInstance;
            }
            catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
                // A previously detected exception with proper bean creation context already,
                // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanCreationException(
                        mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
            }
        }
    

    2.短路操作resolveBeforeInstantiation()

        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;
        }
    

    这里跟FactoryBean#getObject()会调用BeanPostProcessor#postProcessAfterInitialization()一样,也会调用这个方法,因为这里创建的bean也没有经过完整的生命周期,但是也会调用后置处理器初始化后的方法。

    使用示例:

    public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    
        /**
         * InstantiationAwareBeanPostProcessor中自定义的方法
         * 在方法实例化之前执行  Bean对象还没有
         */
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            System.out.println("--->postProcessBeforeInstantiation");
    
            // 利用cglib动态代理生成对象返回
            if (beanClass == Student.class) {
                Enhancer e = new Enhancer();
                e.setSuperclass(beanClass);
                e.setCallback(new MethodInterceptor() {
                    @Override
                    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
                        System.out.println("目标方法执行前:" + method);
                        Object object = methodProxy.invokeSuper(obj, objects);
                        System.out.println("目标方法执行后:" + method + "\n");
                        return object;
                    }
                });
                Student student = (Student) e.create();
                // 返回代理类
                return student;
            }
    
            return null;
        }
    }
    

    配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
        <bean class="com.wz.spring.instantiation.Student" id="student" init-method="start">
            <constructor-arg index="0" value="1"></constructor-arg>
            <constructor-arg index="1" value="小刘"></constructor-arg>
        </bean>
    
        <!-- 注册InstantiationAwareBeanPostProcessor对象 -->
        <bean class="com.wz.spring.instantiation.MyInstantiationAwareBeanPostProcessor"></bean>
    
    </beans>
    

    结果:

    目标方法执行前:public void com.wz.spring.instantiation.Student.study()
    因为学习让我们相遇...
    目标方法执行后:public void com.wz.spring.instantiation.Student.study()
    
    

    3.AbstractAutowireCapableBeanFactory#doCreateBean主流程

        protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {
    
            // Instantiate the bean.
            //包装对象,内部最核心的字段就是咱们的真实实例。它提供了一些额外的接口方法,比如 属性访问器
            BeanWrapper instanceWrapper = null;
            if (mbd.isSingleton()) {
                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
            }
            if (instanceWrapper == null) {
                //该方法创建出来真实的bean实例,并且将其包装到BeanWrapper实例中。
                instanceWrapper = createBeanInstance(beanName, mbd, args);
            }
            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 {
                        //后处理器调用点:合并bd信息,因为接下来就是populate处理依赖了..
                        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");
                }
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
            // Initialize the bean instance.
            Object exposedObject = bean;
            try {
                //处理当前实例的依赖数据...依赖注入在这一步完成的。
                populateBean(beanName, mbd, instanceWrapper);
                //生命周期中的初始化方法的调用。
                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);
                //条件成立:说明当前bean实例 从 2级缓存获取到了...
                //说明产生循环依赖了...3级缓存 当前对象的ObjectFactory.getObject() 被调用过
                if (earlySingletonReference != null) {
                    //条件成立有几种情况?
                    //1.当前“真实实例”不需要被代理
                    //2.当前“实例”已经被代理过了...是在ObjectFactory.getObject() 方法调用时 实现的增强代理。
                    if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                    }
                    else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                        //获取依赖当前bean的 其它beanName
                        String[] dependentBeans = getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                        for (String dependentBean : dependentBeans) {
                            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                actualDependentBeans.add(dependentBean);
                            }
                        }
                        //为什么有问题?
                        //因为咱们当前对象的AOP操作是在 当前方法的 initializeBean 这个方法完成的。
                        //在这之前 外部其它bean持有到的当前的 “bean实例” 都是尚未增强的。
                        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 " +
                                    "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                        }
                    }
                }
            }
    
            // Register bean as disposable.
            try {
                //判断当前bean实例是否需要注册 析构回调。当容器销毁时,会给当前bean的析构方法进行回调。
                registerDisposableBeanIfNecessary(beanName, bean, mbd);
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
            }
    
            return exposedObject;
        }
    

    3.1 this.factoryBeanInstanceCache.remove(beanName)关于FactoryBean

    // 这里申明了一个FactoryBean,并且通过@DependsOn注解申明了这个FactoryBean的创建要在orderService之后,主要目的是为了在DmzFactoryBean创建前让容器发生一次属性注入
    @Component
    @DependsOn("orderService")
    public class DmzFactoryBean implements FactoryBean<DmzService> {
     @Override
     public DmzService getObject() throws Exception {
      return new DmzService();
     }
    
     @Override
     public Class<?> getObjectType() {
      return DmzService.class;
     }
    }
    
    // 没有通过注解的方式将它放到容器中,而是通过上面的DmzFactoryBean来管理对应的Bean
    public class DmzService {
    }
    
    // OrderService中需要注入dmzService
    @Component
    public class OrderService {
     @Autowired
     DmzService dmzService;
    }
    
    

    DmzFactoryBean是依赖于orderService的,所以必定会先创建orderService再创建DmzFactoryBean。
    orderService属性注入阶段:


    为orderService进行属性注入可以分为这么几步

    • 找到需要注入的注入点,也就是orderService中的dmzService字段
    • 根据字段的类型以及名称去容器中查询符合要求的Bean
    • 当遍历到一个FactroyBean时,为了确定其getObject方法返回的对象的类型需要创建这个FactroyBean(只会到对象级别),然后调用这个创建好的FactroyBean的getObjectType方法明确其类型并与注入点需要的类型比较,看是否是一个候选的Bean,在创建这个FactroyBean时就将其放入了factoryBeanInstanceCache中。
    • 在确定了唯一的候选Bean之后,Spring就会对这个Bean进行创建,创建的过程又经过三个步骤

    在创建对象时,因为此时factoryBeanInstanceCache已经缓存了这个Bean对应的对象,所以直接通过this.factoryBeanInstanceCache.remove(beanName)这行代码就返回了,避免了二次创建对象。

    3.2 扩展点applyMergedBeanDefinitionPostProcessors()

            // Allow post-processors to modify the merged bean definition.
            synchronized (mbd.postProcessingLock) {
                if (!mbd.postProcessed) {
                    try {
                        //后处理器调用点:合并bd信息,因为接下来就是populate处理依赖了..
                        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                    }
                    catch (Throwable ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Post-processing of merged bean definition failed", ex);
                    }
                    mbd.postProcessed = true;
                }
            }
    
        protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                //AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition
                //做了一件事:提取出来当前beanType类型整个继承体系内的 @Autowired @Value @Inject 信息 并且包装成一个InjectionMetadata的一个
                //对象,存放到 AutowiredAnnotationBeanPostProcessor 它的缓存中了,key是 beanName。
                if (bp instanceof MergedBeanDefinitionPostProcessor) {
                    MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                    bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
                }
            }
        }
    

    重点看看AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:

    AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition做了一件事:提取出来当前beanType类型整个继承体系内的 @Autowired @Value @Inject 信息 并且包装成一个InjectionMetadata的一个对象,存放到 AutowiredAnnotationBeanPostProcessor 它的缓存中了,key是 beanName。

        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
            InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
            metadata.checkConfigMembers(beanDefinition);
        }
    
        private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
            // Fall back to class name as cache key, for backwards compatibility with custom callers.
            String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
            // Quick check on the concurrent map first, with minimal locking.
            InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                synchronized (this.injectionMetadataCache) {
                    metadata = this.injectionMetadataCache.get(cacheKey);
                    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                        if (metadata != null) {
                            metadata.clear(pvs);
                        }
                        // 获取当前clazz关注的@Autowired @Value @Inject注解信息
                        metadata = buildAutowiringMetadata(clazz);
                        this.injectionMetadataCache.put(cacheKey, metadata);
                    }
                }
            }
            return metadata;
        }
    

    3.3 依赖注入populateBean()

    详情请参考:https://www.jianshu.com/p/bbf51b8553d9?v=1670512502259

    3.4 初始化initializeBean()

        protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }, getAccessControlContext());
            }
            else {
                invokeAwareMethods(beanName, bean);
            }
    
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
                //后处理器调用点:BeforeInitialization   初始化之前的后处理器调用点
                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()) {
                //后处理器调用点:AfterInitialization 初始化之后的后处理器的调用点
                //典型应用:Spring AOP的实现
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
    
            return wrappedBean;
        }
    
        protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
                throws Throwable {
    
            boolean isInitializingBean = (bean instanceof InitializingBean);
            if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
                }
                if (System.getSecurityManager() != null) {
                    try {
                        AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }, getAccessControlContext());
                    }
                    catch (PrivilegedActionException pae) {
                        throw pae.getException();
                    }
                }
                else {
                    //完成afterPropertiesSet接口方法调用
                    ((InitializingBean) bean).afterPropertiesSet();
                }
            }
    
            if (mbd != null && bean.getClass() != NullBean.class) {
                String initMethodName = mbd.getInitMethodName();
                //通过接口实现了的话,就不会再调用使用init-method定义的方法了
                if (StringUtils.hasLength(initMethodName) &&
                        !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                        !mbd.isExternallyManagedInitMethod(initMethodName)) {
                    invokeCustomInitMethod(beanName, bean, mbd);
                }
            }
        }
    

    3.5 注册销毁方法registerDisposableBeanIfNecessary()

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
        AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
        //条件一:原型不会注册 销毁回调方法。
        if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
            if (mbd.isSingleton()) {
                // Register a DisposableBean implementation that performs all destruction
                // work for the given bean: DestructionAwareBeanPostProcessors,
                // DisposableBean interface, custom destroy method.
                //给当前单实例注册回调适配器。 适配器内
                // 根据当前bean实例是继承接口 还是 通过自定义
                // 来决定具体调用哪个方法 完成销毁操作。
                registerDisposableBean(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
            else {
                // A bean with a custom scope...
                Scope scope = this.scopes.get(mbd.getScope());
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
                }
                scope.registerDestructionCallback(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
        }
    }
    
        public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
                List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
    
            Assert.notNull(bean, "Disposable bean must not be null");
            this.bean = bean;
            this.beanName = beanName;
            this.invokeDisposableBean =
                    (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
            this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
            this.acc = acc;
            String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
            if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
                    !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
                this.destroyMethodName = destroyMethodName;
                Method destroyMethod = determineDestroyMethod(destroyMethodName);
                if (destroyMethod == null) {
                    if (beanDefinition.isEnforceDestroyMethod()) {
                        throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
                                destroyMethodName + "' on bean with name '" + beanName + "'");
                    }
                }
                else {
                    Class<?>[] paramTypes = destroyMethod.getParameterTypes();
                    if (paramTypes.length > 1) {
                        throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
                                beanName + "' has more than one parameter - not supported as destroy method");
                    }
                    else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
                        throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
                                beanName + "' has a non-boolean parameter - not supported as destroy method");
                    }
                    destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
                }
                this.destroyMethod = destroyMethod;
            }
            this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
        }
    

    4.创建实例createBeanInstance()

        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
            // Make sure bean class is actually resolved at this point.
            //返回mbd中真实bean的Class对象。
            Class<?> beanClass = resolveBeanClass(mbd, beanName);
    
            //三个条件想表达的意思:bd中如果nonPublicAccessAllowed字段值为true,表示class是非公开类型的 也可以创建实例,反之false,说明是无法创建的..
            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());
            }
    
            // InstanceSupplier
            Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
            if (instanceSupplier != null) {
                return obtainFromSupplier(instanceSupplier, beanName);
            }
    
            //bean标签中配置了 factory-method的情况处理
            // bd中提供了factoryMethodName属性,那么要使用工厂方法的方式来创建对象,
            // 工厂方法又会区分静态工厂方法跟实例工厂方法
            if (mbd.getFactoryMethodName() != null) {
                return instantiateUsingFactoryMethod(beanName, mbd, args);
            }
    
            // Shortcut when re-creating the same bean...
            //表示bd对应的构造信息是否已经解析成可以反射调用的构造方法method信息了
            // 是否推断过构造方法
            boolean resolved = false;
            //是否自动匹配构造方法,构造方法是否需要注入(参数)
            boolean autowireNecessary = false;
            if (args == null) {
                synchronized (mbd.constructorArgumentLock) {
                    //条件成立:说明bd的构造信息已经转化成可以反射调用的method了
                    if (mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        //当resolvedConstructorOrFactoryMethod 有值时,且构造方法有参数,那么可以认为这个字段值就是true。
                        //只有什么情况下这个字段是false呢?
                        //1.resolvedConstructorOrFactoryMethod == null
                        //2.当resolvedConstructorOrFactoryMethod 表示的是默认的构造方法,无参构造方法。
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }
            if (resolved) {
                // 构造函数已经解析过了,并且这个构造函数在调用时需要自动注入参数
                if (autowireNecessary) {
                    //有参数,那么就需要根据参数 去匹配合适的构造方法了...
                    //拿出当前Class的所有构造器,然后根据参数信息 去匹配出一个最优的选项,然后执行最优的 构造器 创建出实例。
                    // 此时部分解析好的参数已经存在了beanDefinition中,并且构造函数也在bd中
                    // 那么在这里只会从缓存中去取构造函数以及参数然后反射调用
                    return autowireConstructor(beanName, mbd, null, null);
                }
                else {
                    //无参构造方法处理
                    return instantiateBean(beanName, mbd);
                }
            }
    
            // Candidate constructors for autowiring?
            //  典型的应用:@Autowired 注解打在了 构造器方法上。参考@Autowired AutowiredAnnotationBeanPostProcessor
            Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
            //条件一:ctors不为null:说明存在1个或多个@Autowired标注的方法。
            // 再进一步选择一个差异值最小的,参数最长的构造函数
            //条件二:mbd autowiredMode 一般情况是no
            // 没有@Autowired标注的方法,但是需要进行自动注入,
            // 那么通过autowireConstructor会去遍历类中申明的所有构造函数,
            // 并查找一个差异值最小的,参数最长的构造函数
            //条件三:条件成立,说明bean信息中配置了 构造参数信息。
            // 说明不是自动注入,配置文件中配置了构造函数要使用的参数
            //条件四:getBean时,args有参数
            if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
                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);
        }
    

    4.1 通过factory-method创建bean

    详情参见: https://www.jianshu.com/p/c9ab0026be34?v=1670424944028

        protected BeanWrapper instantiateUsingFactoryMethod(
                String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    
            return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
        }
    

    ConstructorResolver用来解析构造函数跟工厂方法的代理者,并且它是通过参数匹配的方式来进行推断构造方法或者工厂方法。

    三个参数:

    • beanName:当前要实例化的Bean的名称
    • mbd:当前要实例化的Bean对应的BeanDefinition
    • explicitArgs:这个参数在容器启动阶段我们可以认定它就是null,只有显示的调用了getBean方法,并且传入了明确的参数,例如:getBean(“dmzService”,“hello”)这种情况下才会不为null。

    4.2 通过构造方法创建bean

    详情参见: https://www.jianshu.com/p/1b487205dbb6?v=1670428900594

    5.factory-method跟构造函数的比较

    通过构造函数实例化对象,多了一层处理,就是要处理构造函数上的@Autowired注解以及方法上的@LookUp注解(要决定选取哪一种实例化策略,SimpleInstantiationStrategy/CglibSubclassingInstantiationStrategy)。

    在最终的选取也存在差异,对于facotyMehod而言,在宽松模式下(除ConfigurationClassBeanDefinition外,也就是扫描@Bean得到的BeanDefinition,都是宽松模式),会选取一个最精准的方法,在严格模式下,会选取一个参数最长的方法。

    对于构造函数而言,会必定会选取一个参数最长的方法。



    6.计算类型差异

    集中情况说明:

    • 1、factoryMethod+宽松模式:会选取一个最精确的方法,同时方法的参数要尽量长
    • 2、factoryMethod+严格模式:会选取一个参数尽量长的方法
    • 3、构造函数+宽松模式:会选取一个参数尽量长的方法
                    //typeDiffWeight 数值越高说明构造器与参数匹配度越低...
                    //计算出当前构造器参数类型 与 当前 构造器参数 匹配度。
                    int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                    // Choose this constructor if it represents the closest match.
                    //条件成立:说明当前循环处理的 构造器 比上一次筛选出来的构造器 更优先。
                    if (typeDiffWeight < minTypeDiffWeight) {
                        constructorToUse = candidate;
                        argsHolderToUse = argsHolder;
                        argsToUse = argsHolder.arguments;
                        minTypeDiffWeight = typeDiffWeight;
                        ambiguousConstructors = null;
                    }
    

    判断bd是严格模式还是宽松模式,bd默认就是宽松模式,只有在ConfigurationClassBeanDefinition中使用严格模式,也就是扫描@Bean标注的方法注册的bd(对应的代码可以参考:ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod方法)

    宽松模式:

    public int getTypeDifferenceWeight(Class<?>[] paramTypes) {
        // 计算实际使用的参数跟方法声明的参数的差异值
       int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);
        // 计算没有经过类型转换的参数跟方法声明的参数的差异值
       int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
       return (rawTypeDiffWeight < typeDiffWeight ? rawTypeDiffWeight : typeDiffWeight);
      }
    
    public static int getTypeDifferenceWeight(Class<?>[] paramTypes, Object[] args) {
        int result = 0;
        for (int i = 0; i < paramTypes.length; i++) {
            // 在出现类型转换时,下面这个判断才会成立,也就是在比较rawArguments跟paramTypes的差异时才可能满足这个条件
            if (!ClassUtils.isAssignableValue(paramTypes[i], args[i])) {
                return Integer.MAX_VALUE;
            }
            if (args[i] != null) {
                Class<?> paramType = paramTypes[i];
                Class<?> superClass = args[i].getClass().getSuperclass();
                while (superClass != null) {
                    // 如果我们传入的值是方法上声明的参数的子类,那么每多一层继承关系,差异值加2
                    if (paramType.equals(superClass)) {
                        result = result + 2;
                        superClass = null;
                    }
                    else if (ClassUtils.isAssignable(paramType, superClass)) {
                        result = result + 2;
                        superClass = superClass.getSuperclass();
                    }
                    else {
                        superClass = null;
                    }
                }
                // 判断方法的参数是不是一个接口,如果是,那么差异值加1
                if (paramType.isInterface()) {
                    result = result + 1;
                }
            }
        }
        return result;
    }
    
    

    严格模式:

    public int getAssignabilityWeight(Class<?>[] paramTypes) {
        // 严格模式下,只有三种返回值
        // 1.Integer.MAX_VALUE,经过类型转换后还是不符合要求,返回最大的类型差异
        // 因为解析后的参数可能返回一个NullBean(创建对象的方法返回了null,Spring会将其包装成一个NullBean),不过一般不会出现这种情况,所以我们可以当这种情况不存在
       for (int i = 0; i < paramTypes.length; i++) {
        if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
         return Integer.MAX_VALUE;
        }
       }
        // 2.Integer.MAX_VALUE - 512,进行过了类型转换才符合要求
       for (int i = 0; i < paramTypes.length; i++) {
        if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
         return Integer.MAX_VALUE - 512;
        }
       }
        // 3.Integer.MAX_VALUE - 1024,没有经过类型转换就已经符合要求了,返回最小的类型差异
       return Integer.MAX_VALUE - 1024;
      }
    

    相关文章

      网友评论

          本文标题:AbstractAutowireCapableBeanFacto

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