5、Spring源码-依赖注入(上)

烟雨 4年前 (2021-07-19) 阅读数 358 #Spring源码
文章标签 Spring

一、Spring中到底有几种依赖注入的方式?

首先分两种:

  1. 手动注入

  2. 自动注入

1.1、手动注入

在XML中定义Bean时,就是手动注入,因为是手动给某个属性指定了值

<!-- 这种底层是通过set方法进行注入 -->
<bean name="userService" class="com.zender.service.UserService">
	<property name="orderService" ref="orderService"/>
</bean>
<!-- 这种底层是通过构造方法进行注入 -->
<bean name="userService" class="com.zender.service.UserService">
	<constructor-arg index="0" ref="orderService"/>
</bean>

所以手动注入的底层也就是分为两种:

  1. set方法注入

  2. 构造方法注入

1.2、自动注入

自动注入又分为两种:

XML的autowire自动注入

XML的autowire自动注入,在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式(byType、byName、constructor、default、no):
<bean id="userService" class="com.zender.service.UserService" autowire="byType"/>

这么写,表示Spring会自动的给userService中所有的属性自动赋值(不需要这个属性上有@Autowired注解,但需要这个属性有对应的set方法)。

在创建Bean的过程中,在填充属性时,Spring会去解析当前类,把当前类的所有方法都解析出来,Spring会去解析每个方法得到对应的PropertyDescriptor(属性描述器)对象,PropertyDescriptor(属性描述器)中有几个属性:

  1. name:这个name并不是方法的名字,而是拿方法名字进过处理后的名字。

    1. 如果方法名字以“get”开头,比如“getXXX”,那么name=XXX。

    2. 如果方法名字以“is”开头,比如“isXXX”,那么name=XXX。

    3. 如果方法名字以“set”开头,比如“setXXX”,那么name=XXX。

  2. readMethodRef:表示get方法的Method对象的引用。

  3. readMethodName:表示get方法的名字。

  4. writeMethodRef表示set方法的Method对象的引用。

  5. writeMethodName表示set方法的名字。

  6. propertyTypeRef:如果有get方法那么对应的就是返回值的类型,如果是set方法那么对应的就是set方法中唯一参数的类型。

get方法的定义是: 方法参数个数为0个,并且方法名字以"get"开头 或者 方法名字以"is"开头并且方法的返回类型为boolean。

set方法的定义是:方法参数个数为1个,并且 方法名字以"set"开头并且方法返回类型为void。

所以,Spring在通过byName的自动填充属性时流程是:

  1. 找到所有set方法所对应的XXX部分的名字。

  2. 根据XXX部分的名字去获取bean,进行属性填充。

Spring在通过byType的自动填充属性时流程是:

  1. 获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean,进行属性填充。

  2. 如果找到多个,会报错

如果是constructor,那么就可以不写set方法了,当某个bean是通过构造方法来注入时,spring利用构造方法的参数信息从Spring容器中去找bean,找到bean之后作为参数传给构造方法,从而实例化得到一个bean对象,并完成属性赋值(构造方法注入相当于byType+byName,普通的byType是根据set方法中的参数类型去找bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找bean,如果找到多个会根据参数名确定)。

@Autowired注解的自动注入

@Autowired注解相当于XML中的autowire属性的注解方式的替代

从本质上讲,@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性。

XML中的autowire控制的是整个bean的所有属性,而@Autowired注解是直接写在某个属性、某个set方法、某个构造方法上的。

举个例子,如果一个类有多个构造方法,那么如果用XML的autowire=constructor,你无法控制到底用哪个构造方法,而你可以用@Autowired注解来直接指定你想用哪个构造方法。

同时,用@Autowired注解,还可以控制,哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制。

但是@Autowired无法区分byType和byName,@Autowired是先byType,如果找到多个则byName。

@Autowired注解可以写在:

  1. 属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定。

  2. 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定。

  3. set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定。

二、寻找注入点

想要支持依赖注入,需要先找到需要注入点,缓存起来。

在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()找出注入点并缓存。

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    //寻找切入点并缓存
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

2.1、findAutowiringMetadata()

该方法获取给定类的@Autowired注解信息,解析注入点,并保存到容器缓存中(injectionMetadataCache)。
//获取给定类的@Autowired注解信息
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.
    // 第一次进来metadata为空
    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);
                }
                //解析注入点,并保存
                metadata = buildAutowiringMetadata(clazz);
                //将得到的给定类@Autowired注解信息存储在容器缓存中
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

2.2、buildAutowiringMetadata()

该方法会遍历当前类及其所有基类,解析全部字段和方法,寻找是否存在@Autowired、@Value、@inject中的一个注解,进行解析存放到当前类的注入点集合中。
返回一个InjectionMetadata对象,里面包含了前类的注入点集合。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
		Class<?> targetClass = clazz;

		//遍历当前类及其所有基类,解析全部字段
		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();

			//利用JDK反射机制遍历targetClass中的所有字段,获取字段上的注解信息
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//获取给定字段上的注解,是否存在@Autowired、@Value、@inject中的一个
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//如果给定字段是静态的(static),不会进行注入
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					//判断注解的required属性值是否有效
					boolean required = determineRequiredStatus(ann);
					//构造注入点,添加在返回的集合中
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			//利用JDK反射机制获取给定类中所有的声明方法,获取方法上的注解信息
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                //方法可能是个桥接方法,需要找到原方法进行解析
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				//获取给定方法上的所有注解
				AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					//如果方法是静态的,则直接遍历下一个方法
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					//如果方法的参数列表为空
					if (method.getParameterCount() == 0) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					//判断注解的required属性值是否有效
					boolean required = determineRequiredStatus(ann);
					//获取当前方法的属性描述符,即方法是可读的(readable)getter方法,还是可写的(writeable)setter方法
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					//构造注入点,添加在返回的集合中
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			//将当前类的注入点存放到集合中
			elements.addAll(0, currElements);
			//获取给定类的父类
			targetClass = targetClass.getSuperclass();
		}
		//如果给定类有基类,并且基类不是Object,则递归获取其基类的元信息
		while (targetClass != null && targetClass != Object.class);

		return new InjectionMetadata(clazz, elements);
	}

2.3、static的字段或方法为什么不支持注入

上面的源码看出,static修饰的字段和方法是不支持注入的。
@Component
@Scope("prototype")
public class OrderService {
}

@Component
@Scope("prototype")
public class UserService  {

    @Autowired
    private static OrderService orderService;

    public void test() {
        System.out.println("test123");
    }
}

UserService和OrderService都是原型Bean,假设Spring支持static字段进行自动注入,那么现在调用两次getBean()

UserService userService1 = context.getBean("userService");
UserService userService2 = context.getBean("userService");

问此时,userService1的orderService值是什么?还是它自己注入的值吗?

答案是不是,一旦userService2创建好了之后,static orderService字段的值就发生了修改了,从而出现bug。

三、注入点(方法/字段)进行注入

真正创建Bean的方法:AbstractAutowireCapableBeanFactory#doCreateBean()
//真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    throws BeanCreationException {

    // Instantiate the bean.
    //准备封装被创建的Bean对象
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        //有可能再Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入),缓存中移除
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        //创建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.
    //调用PostProcessor(BeanDefinition的后置处理器)
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                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.
    //向容器中缓存单例模式的Bean对象,以防循环依赖
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                      isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                         "' to allow for resolving potential circular references");
        }
        //这里是一个匿名内部类,为了防止循环依赖,尽早持有对象的引用(也就是添加到三级缓存)
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    //Bean对象的初始化,依赖注入在此触发
    //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
    Object exposedObject = bean;
    try {
        //将Bean实例对象属性填充
        populateBean(beanName, mbd, instanceWrapper);
        //初始化Bean对象
        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) {
        //获取指定名称的已注册的单例模式Bean对象
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            //根据名称获取的已注册的Bean和正在实例化的Bean是同一个
            if (exposedObject == bean) {
                //当前实例化的Bean初始化完成
                exposedObject = earlySingletonReference;
            }
            //当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                //获取当前Bean所依赖的其他Bean
                for (String dependentBean : dependentBeans) {
                    //对依赖Bean进行类型检查
                    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 {
        //注册Bean销毁时的相关操作
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

依赖注入的主要逻辑在AbstractAutowireCapableBeanFactory#populateBean()

//获取容器在解析Bean定义资源时为BeanDefiniton中设置的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//对依赖注入处理,首先处理autowire自动装配的依赖注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
    mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    //MutablePropertyValues是PropertyValues具体的实现类
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

    // Add property values based on autowire by name if applicable.
    //根据Bean名称进行autowire自动装配处理
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }

    // Add property values based on autowire by type if applicable.
    //根据Bean类型进行autowire自动装配处理
    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);

    if (hasInstAwareBpps || needsDepCheck) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                //如果是@Autowired注解/@value注解,会调用AutowiredAnnotationAwareBeanPostProcessor.postProcessPropertyValues方法
                //如果是@resource注解,会调用CommonAnnotationAwareBeanPostProcessor.postProcessPropertyValues方法去处理。
                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);
        }
    }

    if (pvs != null) {
        //为BeanDefiniton中设置的属性,进行注入赋值
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

3.1、autowireByName()方法

根据Bean类型进行autowire自动装配处理,autowireByName()方法:
//根据名称对属性进行自动依赖注入
protected void autowireByName(
    String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    //获取Bean中能进行自动注入的属性名
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    // 遍历每个属性名,并去获取bean对象,并设置到pvs中
    for (String propertyName : propertyNames) {
        //如果Spring IOC容器中包含指定名称的Bean
        if (containsBean(propertyName)) {
            //调用getBean方法向IOC容器索取指定名称的Bean实例,迭代触发属性的初始化和依赖注入
            Object bean = getBean(propertyName);
            //为指定名称的属性赋予属性值
            pvs.add(propertyName, bean);
            //记录propertyName(属性名)是被那个beanName所依赖的
            registerDependentBean(propertyName, beanName);
            if (logger.isDebugEnabled()) {
                logger.debug("Added autowiring by name from bean name '" + beanName +
                             "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                             "' by name: no matching bean found");
            }
        }
    }
}

unsatisfiedNonSimpleProperties(),该方法去获取Bean中能进行自动注入的属性名:

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
        Set<String> result = new TreeSet<>();
        PropertyValues pvs = mbd.getPropertyValues();
        //属性描述器,只能拿到有对应set/get方法的属性
        PropertyDescriptor[] pds = bw.getPropertyDescriptors();
        //什么样的属性能进行自动注入?
        //1、该属性有对应set方法
        //2、没有在ignoredDependencyTypes中
        //3、如果属性对应的set是实现某个接口中所定义的,并且接口也没有在ignoredDependencyTypes中
        //4、属性类型不是简单类型,比如int,Integer,int[]。
        for (PropertyDescriptor pd : pds) {
            if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
                    !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
                result.add(pd.getName());
            }
        }
        return StringUtils.toStringArray(result);
    }

什么样的属性能进行自动注入?

  1. 该属性有对应set方法。

  2. 没有在ignoredDependencyTypes中。

  3. 如果属性对应的set是实现某个接口中所定义的,并且接口也没有在ignoredDependencyTypes中。

  4. 属性类型不是简单类型,比如int,Integer,int[]。

3.2、autowireByType()方法 

//根据类型对属性进行自动依赖注入
protected void autowireByType(
    String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    //获取用户定义的类型转换器
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    //存放解析的要注入的属性
    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    //对Bean对象中非简单属性(不是简单继承的对象,如8中原始类型,字符
    //URL等都是简单属性)进行处理
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        try {
            //获取指定属性名称的属性描述器
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is a unsatisfied, non-simple property.
            //不对Object类型的属性进行autowiring自动依赖注入
            if (Object.class != pd.getPropertyType()) {
                //获取属性的setter方法
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                //检查指定类型是否可以被转换为目标对象的类型
                boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
                //创建一个要被注入的依赖描述
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                //根据容器的Bean定义解析依赖关系,返回所有要被注入的Bean对象
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    //为属性赋值所引用的对象
                    pvs.add(propertyName, autowiredArgument);
                }
                for (String autowiredBeanName : autowiredBeanNames) {
                    //记录propertyName(属性名)是被那些bean所依赖的
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
                                     propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                //释放已自动注入的属性
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}

registerDependentBean()方法

该方法为指定的Bean查找依赖的Bean,并放入dependentBeanMap(某个bean被哪些Bean依赖)dependenciesForBeanMap(某个bean依赖了哪些Bean)
//为指定的Bean查找依赖的Bean
//并放入dependentBeanMap(某个bean被哪些Bean)和dependenciesForBeanMap(某个bean依赖了哪些Bean)中
public void registerDependentBean(String beanName, String dependentBeanName) {
    // A quick check for an existing entry upfront, avoiding synchronization...
    //处理Bean名称,将别名转换为规范的Bean名称
    String canonicalName = canonicalName(beanName);
    Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
    if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) {
        return;
    }

    // No entry yet -> fully synchronized manipulation of the dependentBeans Set
    //多线程同步,保证容器内数据的一致性
    //处理某个bean被哪些Bean依赖了
    synchronized (this.dependentBeanMap) {
        //获取给定名称Bean的所有依赖Bean
        dependentBeans = this.dependentBeanMap.get(canonicalName);
        if (dependentBeans == null) {
            //为Bean设置被依赖Bean信息
            dependentBeans = new LinkedHashSet<>(8);
            this.dependentBeanMap.put(canonicalName, dependentBeans);
        }
        //为Bean设置被依赖Bean信息
        dependentBeans.add(dependentBeanName);
    }
    //处理某个bean依赖了哪些Bean了
    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
        if (dependenciesForBean == null) {
            dependenciesForBean = new LinkedHashSet<>(8);
            this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
        }
        //为Bean设置依赖了Bean信息
        dependenciesForBean.add(canonicalName);
    }
}

四、处理注解 

处理相应的依赖注入的注解(@Autowired、@value、@resource),进行属性注入。
//检查后处理器是否已经准备好了
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//是否需要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

if (hasInstAwareBpps || needsDepCheck) {
    if (pvs == null) {
        pvs = mbd.getPropertyValues();
    }
    PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    if (hasInstAwareBpps) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //如果是@Autowired注解/@value注解,会调用AutowiredAnnotationAwareBeanPostProcessor.postProcessPropertyValues方法
            //如果是@resource注解,会调用CommonAnnotationAwareBeanPostProcessor.postProcessPropertyValues方法去处理。
            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);
    }
}

if (pvs != null) {
    //为BeanDefiniton中设置的属性,进行注入赋值
    applyPropertyValues(beanName, mbd, bw, pvs);
}

如果是@Autowired注解/@value注解,会调用AutowiredAnnotationAwareBeanPostProcessor#postProcessPropertyValues()方法处理。

//处理类中的属性
@Override
public PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

    //获取指定类中autowire相关注解的元信息
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        //对Bean的属性进行自动注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}

如果是@resource注解,会调用CommonAnnotationAwareBeanPostProcessor#postProcessPropertyValues()方法去处理。

//对字段进行注入
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    //获取注入元素对象
    Field field = (Field) this.member;
    Object value;
    //如果当前对象在容器中被缓存
    if (this.cached) {
        //根据Bean名称解析缓存中的字段值
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    //如果当前对象没有被容器缓存
    else {
        //创建一个字段依赖描述符
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
        Assert.state(beanFactory != null, "No BeanFactory available");
        //获取容器中的类型转换器
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            //根据容器中Bean定义,解析指定的依赖关系,获取依赖对象
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        //线程同步,确保容器中数据一致性
        synchronized (this) {
            //如果当前对象没有被容器缓存
            if (!this.cached) {
                //获取到了当前对象的依赖对象,并且required属性为true
                if (value != null || this.required) {
                    this.cachedFieldValue = desc;
                    //为指定Bean注册依赖Bean
                    registerDependentBeans(beanName, autowiredBeanNames);
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        //如果容器中有指定名称的Bean对象
                        if (beanFactory.containsBean(autowiredBeanName)) {
                            //依赖对象类型和字段类型匹配,默认按类型注入
                            if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                //创建一个依赖对象的引用,同时缓存
                                this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                    desc, autowiredBeanName, field.getType());
                            }
                        }
                    }
                }
                //如果获取的依赖关系为null,且获取required属性为false
                else {
                    //将字段值的缓存设置为null
                    this.cachedFieldValue = null;
                }
                //容器已经对当前字段的值缓存
                this.cached = true;
            }
        }
    }
    //如果字段依赖值不为null
    if (value != null) {
        //显式使用JDK的反射机制,设置自动的访问控制权限为允许访问
        ReflectionUtils.makeAccessible(field);
        //为Bean对象的字段设置值
        field.set(bean, value);
    }
}

4.1、注入点进行注入

Spring在AbstractAutowireCapableBeanFactory#populateBean()中会调用InstantiationAwareBeanPostProcessor接口的实现类的postProcessProperties()方法,去遍历所找到的注入点依次进行注入。
里面有个metadata.inject()方法,根据注入点的不同(方法/属性),调用相应的InjectedElement类的子类的inject()方法去处理。
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectedElement> elementsToIterate =
        (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        boolean debug = logger.isDebugEnabled();
        for (InjectedElement element : elementsToIterate) {
            if (debug) {
                logger.debug("Processing injected element of bean '" + beanName + "': " + element);
            }
            element.inject(target, beanName, pvs);
        }
    }
}

属性

处理注入点为属性的子类方法是:AutowiredFieldElement#inject()。
//对字段进行注入
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    //获取注入元素对象
    Field field = (Field) this.member;
    Object value;
    //如果当前对象在容器中被缓存
    if (this.cached) {
        //根据Bean名称解析缓存中的字段值
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    //如果当前对象没有被容器缓存
    else {
        //创建一个字段依赖描述符
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
        Assert.state(beanFactory != null, "No BeanFactory available");
        //获取容器中的类型转换器
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            //根据容器中Bean定义,解析指定的依赖关系,获取依赖对象
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        //线程同步,确保容器中数据一致性
        synchronized (this) {
            //如果当前对象没有被容器缓存
            if (!this.cached) {
                //获取到了当前对象的依赖对象,并且required属性为true
                if (value != null || this.required) {
                    this.cachedFieldValue = desc;
                    //为指定Bean注册依赖Bean
                    registerDependentBeans(beanName, autowiredBeanNames);
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        //如果容器中有指定名称的Bean对象
                        if (beanFactory.containsBean(autowiredBeanName)) {
                            //依赖对象类型和字段类型匹配,默认按类型注入
                            if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                //创建一个依赖对象的引用,同时缓存
                                this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                    desc, autowiredBeanName, field.getType());
                            }
                        }
                    }
                }
                //如果获取的依赖关系为null,且获取required属性为false
                else {
                    //将字段值的缓存设置为null
                    this.cachedFieldValue = null;
                }
                //容器已经对当前字段的值缓存
                this.cached = true;
            }
        }
    }
    //如果字段依赖值不为null
    if (value != null) {
        //显式使用JDK的反射机制,设置自动的访问控制权限为允许访问
        ReflectionUtils.makeAccessible(field);
        //为Bean对象的字段设置值
        field.set(bean, value);
    }
}

方法

处理注入点为方法的子类方法是:AutowiredMethodElement#inject()。
//对方法进行注入
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    //如果属性被显式设置为skip,则不进行注入
    if (checkPropertySkipping(pvs)) {
        return;
    }
    //获取注入元素对象
    Method method = (Method) this.member;
    Object[] arguments;
    //如果容器对当前方法缓存
    if (this.cached) {
        // Shortcut for avoiding synchronization...
        //获取缓存中指定Bean名称的方法参数
        arguments = resolveCachedArguments(beanName);
    }
    //如果没有缓存
    else {
        //获取方法的参数列表
        Class<?>[] paramTypes = method.getParameterTypes();
        //创建一个存放方法参数的数组
        arguments = new Object[paramTypes.length];
        DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
        Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
        Assert.state(beanFactory != null, "No BeanFactory available");
        //获取容器的类型转换器
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        for (int i = 0; i < arguments.length; i++) {
            //创建方法参数对象
            MethodParameter methodParam = new MethodParameter(method, i);
            DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
            currDesc.setContainingClass(bean.getClass());
            //解析方法的输入参数,为方法参数创建依赖描述符
            descriptors[i] = currDesc;
            try {
                Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
                if (arg == null && !this.required) {
                    arguments = null;
                    break;
                }
                //根据容器中Bean定义解析依赖关系,获取方法参数依赖对象
                arguments[i] = arg;
            }
            catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
            }
        }
        //线程同步,以确保容器中数据一致性
        synchronized (this) {
            //如果当前方法没有被容器缓存
            if (!this.cached) {
                //如果方法的参数列表不为空
                if (arguments != null) {
                    //为容器中缓存方法参数的对象赋值
                    Object[] cachedMethodArguments = new Object[paramTypes.length];
                    for (int i = 0; i < arguments.length; i++) {
                        cachedMethodArguments[i] = descriptors[i];
                    }
                    //为指定Bean注册依赖Bean
                    registerDependentBeans(beanName, autowiredBeans);
                    //如果依赖对象集合大小等于方法参数个数
                    if (autowiredBeans.size() == paramTypes.length) {
                        Iterator<String> it = autowiredBeans.iterator();
                        //为方法参数设置依赖对象
                        for (int i = 0; i < paramTypes.length; i++) {
                            String autowiredBeanName = it.next();
                            //如果容器中存在指定名称的Bean对象
                            if (beanFactory.containsBean(autowiredBeanName)) {
                                //如果参数类型和依赖对象类型匹配
                                if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
                                    //创建一个依赖对象的引用,复制给方法相应的参
                                    cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
                                        descriptors[i], autowiredBeanName, paramTypes[i]);
                                }
                            }
                        }
                    }
                    this.cachedMethodArguments = cachedMethodArguments;
                }
                //如果方法参数列表为null,则设置容器对该方法参数的缓存为null
                else {
                    this.cachedMethodArguments = null;
                }
                //设置容器已经对该方法缓存
                this.cached = true;
            }
        }
    }
    //如果方法参数依赖对象不为null
    if (arguments != null) {
        try {
            //使用JDK的反射机制,显式设置方法的访问控制权限为允许访问
            ReflectionUtils.makeAccessible(method);
            //调用Bean的指定方法
            method.invoke(bean, arguments);
        }
        catch (InvocationTargetException ex){
            throw ex.getTargetException();
        }
    }
}

image.png

版权声明

非特殊说明,本文由Zender原创或收集发布,欢迎转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

作者文章
热门