Spring之依赖注入底层源码解析(一)

Spring之依赖注入底层源码解析

  • Spring依赖注入底层流程图
  • Spring中依赖注入的方式
    • 手动注入
    • 自动注入
  • @Autowired自动注入
  • 寻找注入点
    • static的字段或方法为什么不支持依赖注入
    • 桥接方法
  • 注入点进行注入
    • 字段注入
    • set方法注入
    • 注入点注入流程图

Spring依赖注入底层流程图

Spring中Bean的依赖注入原理.jpeg

  1. 首先先去找到所有注入点,注入点分为两种: 被@Autowired注解了的属性 以及 被@Autowired注解了的方法
  2. 遍历每个注入点
  3. 根据注入点去找Bean,这里如果注解了属性的会根据属性的类型去找Bean,如果注解了的是方法,那就根据方法中的参数类型去找Bean
  4. 对于找到有几个Bean
    1. 如果找到一个Bean,直接把这个Bean进行注入
    2. 如果找到多个Bean,会从多个Bean中确定出一个Bean
      1. 先判断是不是isAutowiredCandidate
      2. 再判断是不是复合Qualifier
      3. 如果还有多个,取@Primary的Bean
      4. 取出优先级最高的Bean
      5. 根据名字进行筛选,筛选出唯一的Bean
        1. 如果是根据属性注入的,那么就是根据属性名字去找
        2. 如果是根据set方法,那就是参数名字
    3. 如果没有找到Bean
      1. 如果@Autowired的reuqired属性为true,也就是说注入点必须被注入,那么就会报错

Spring中依赖注入的方式

对于Spring中依赖注入的方式,分为两种:

  • 手动注入
    • set方法注入
    • 构造方法注入
  • 自动注入
    • XML的autowire自动注入
    • @Autowired注解的自动注入

手动注入

在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定的值,下面这种底层是通过set方法进行注入

<bean name="userService" class="linc.fun.service.UserService"> 
	<property name="orderService" ref="orderService"/> 
</bean>

下面这种是通过构造方法进行注入

<bean name="userService" class="linc.fun.service.UserService"> 
	<constructor‐arg index="0" ref="orderService"/> 
</bean>

自动注入

自动注入又分为两种

  • XML的autowire自动注入
  • @Autowired注解的自动注入

XML的autowire自动注入

在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式:

  • byType
  • byName
  • constructor
  • default
  • no
<bean id="userService" class="linc.fun.service.UserService" autowire="byType"/>

如果这么写,表示Spring会自动的给userService中所有的属性进行自动赋值,不需要在属性上加@Autowired注解,但需要这个属性有对应的set方法

PropertyDescriptor对象

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

public class PropertyDescriptor extends FeatureDescriptor {
    private Reference<? extends Class<?>> propertyTypeRef;
    private final MethodRef readMethodRef = new MethodRef();
    private final MethodRef writeMethodRef = new MethodRef();
    private Reference<? extends Class<?>> propertyEditorClassRef;

    private boolean bound;
    private boolean constrained;

    // The base name of the method name which will be prefixed with the
    // read and write method. If name == "foo" then the baseName is "Foo"
    private String baseName;

    private String writeMethodName;
    private String readMethodName;
  
    public PropertyDescriptor(String propertyName, Class<?> beanClass)
                throws IntrospectionException {
        this(propertyName, beanClass,
                Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName),
                Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
    }
	.....
}
static final String GET_PREFIX = "get";
static final String SET_PREFIX = "set";
static final String IS_PREFIX = "is";
  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,set方法的定义

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

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

byName自动填充属性时的流程

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

  • 找到所有set方法所对应的XXX部分的名字
  • 根据XXX部分的名字去获取Bean

byType的自动填充属性时的流程

  • 获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取Bean
  • 如果找到多个,会报错

constructor注入

以上,分析了autowire的byType和byName情况,那么接下来分析constructor,constructor表示通过构造方法注入,其实这种情况就比较简单了,没有byType和byName那么复杂

如果是constructor,那么就可以不写set方法了,当某个Bean是通过构造方法来注入时,Spring利用构造方法的参数信息从Spring容器中去找Bean,找到Bean之后作为参数传给构造方法,从而实例化得到一个Bean对象,并完成属性赋值(属性赋值的代码需要程序员来实现)

这里,我们只考虑只有一个有参数构造方法,其实构造方法注入相当于 byType+byName ,普通的byType是根据set方法的参数类型去找Bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找Bean,如果找到多个会根据参数名确定

为什么选择使用@Autowired,而不用XML的形式呢

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

官网如下解释: 从本质上将,@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性

Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine‐grained control and wider applicability

这里强调的是更细粒度的控制

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

倘若我们使用XML的形式,如果用XML中的autowire=constructor,在拥有多个构造方法的情况下,无法进行很好的控制,但是通过@Autowired注解可以直接指定想用哪个构造方法

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

但是@Autowird无法区分byType和byName,@Autowired是先byType,如果找到多个就会选择byName

那么XML的自动注入底层其实也就是

  • set方法注入
  • 构造方法注入

@Autowired注解的自动注入

@Autowired注解是byType+byName的结合

对于@Autowired注解可以有如下几种使用方式

  • 属性上: 先根据属性类型去找Bean,如果找到多个再根据属性名去确定一个
  • 构造方法: 现根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个
  • set方法上: 先根据方法参数类型去找Bean,如果找到多个再根据参数名去确定一个

对于底层到了

  • 属性注入
  • set方法注入
  • 构造方法注入

寻找注入点

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

/**
 *  实例化后的合并BeanDefinition之后的BeanDefinition进行处理
 *  找注入点
 */
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}
/**
 * 寻找注入点,看哪些需要注入,哪些set方法上加了注解
 */
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);
			}
			// 解析注入点并缓存
			metadata = buildAutowiringMetadata(clazz);
			this.injectionMetadataCache.put(cacheKey, metadata);
		}
	}
}
return metadata;
}

找注入点的流程

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
	// 如果一个Bean的类型是String...,那么则根本不需要进行依赖注入
	if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
		return InjectionMetadata.EMPTY;
	}

	List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
	Class<?> targetClass = clazz;

	do {
		final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

		// 遍历targetClass中的所有Field
		ReflectionUtils.doWithLocalFields(targetClass, field -> {
			// field上是否存在@Autowired、@Value、@Inject中的其中一个
			MergedAnnotation<?> ann = findAutowiredAnnotation(field);
			if (ann != null) {
				// static filed不是注入点,不会进行自动注入
				// 在两个bean都是原型bean的情况下,其中一个是static bean注入,可能导致对象内部属性的值发生变化
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}

				// 构造注入点
				boolean required = determineRequiredStatus(ann);
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});

		// 遍历targetClass中的所有Method
		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			// 处理桥接方法 泛型的时候,字节码会有两个set方法
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				return;
			}
			// method上是否存在@Autowired、@Value、@Inject中的其中一个
			MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
				// static method不是注入点,不会进行自动注入
				if (Modifier.isStatic(method.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static methods: " + method);
					}
					return;
				}
				// set方法最好有入参,没有就会打印一条日志
				if (method.getParameterCount() == 0) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation should only be used on methods with parameters: " +
								method);
					}
				}
				// 判断是否是required = true 如果是,但是没找到可以赋值给它就会报错,false就没事
				boolean required = determineRequiredStatus(ann);
				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
				currElements.add(new AutowiredMethodElement(method, required, pd));
			}
		});
		// 父类的会放在最前面
		elements.addAll(0, currElements);
		targetClass = targetClass.getSuperclass(); // 找父类的
	}
	while (targetClass != null && targetClass != Object.class);

	// 返回并且缓存
	return InjectionMetadata.forElements(elements, clazz);
}

寻找注入点.jpeg

  1. 遍历当前类的所有的属性字段field
  2. 查看字段上是否存在@Autowired、@Value、@Inject中其中任意一个,存在则认为该字段是一个注入点
  3. 如果字段是static,则不进行注入
  4. 获取@Autowired中的required属性的值
  5. 将字段信息构建成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中
  6. 遍历当前类的所有方法Method
  7. 判断当前Method是否存在桥接方法,如果是,找到原方法
  8. 查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法是一个注入点
  9. 如果方法是static的,则不进行注入
  10. 获取@Autowired中的required属性的值
  11. 将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到currElements集合中
  12. 遍历完当前类的字段和方法后,将遍历父类的,直到没有父类
  13. 最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并且缓存

static的字段或方法为什么不支持依赖注入

@Component
@Scope("prototype")
public class CService {
}

@Component
@Scope("prototype")
public class DService {
	@Autowired
	private static CService cService;

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

在CService和DService都是原型Bean的情况下,倘若Spring支持static字段进行自动注入,那么现在调用两次

@Test
public void testPrototypeStatic() {
	AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
	DService d1 = ctx.getBean(DService.class);
	DService d2 = ctx.getBean(DService.class);
}

对于此时,d1的CService值是什么?还是它自己注入的值吗

很显然不是,一旦d2创建好了,static Cservice字段的值就发生了改变了,从而会出现bug

桥接方法

// class version 52.0 (52)
// access flags 0x21
// signature Ljava/lang/Object;Llinc/cool/service/UserInterface<Llinc/cool/service/OrderService;>;
// declaration: linc/cool/service/UserService implements linc.cool.service.UserInterface<linc.cool.service.OrderService>
public class linc/cool/service/UserService implements linc/cool/service/UserInterface {

  // compiled from: UserService.java

  // access flags 0x2
  private Llinc/cool/service/OrderService; orderService

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 10 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public test()V
   L0
    LINENUMBER 13 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 0
    INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
    INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String;
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    LDC ".test()"
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 14 L1
    RETURN
   L2
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
    MAXSTACK = 3
    MAXLOCALS = 1

  // access flags 0x1
  public setOrderService(Llinc/cool/service/OrderService;)V
  @Lorg/springframework/beans/factory/annotation/Autowired;()
   L0
    LINENUMBER 22 L0
    ALOAD 0
    ALOAD 1
    PUTFIELD linc/cool/service/UserService.orderService : Llinc/cool/service/OrderService;
   L1
    LINENUMBER 24 L1
    RETURN
   L2
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L2 0
    LOCALVARIABLE orderService Llinc/cool/service/OrderService; L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1041 桥接方法
  public synthetic bridge setOrderService(Ljava/lang/Object;)V
  @Lorg/springframework/beans/factory/annotation/Autowired;()
   L0
    LINENUMBER 10 L0
    ALOAD 0
    ALOAD 1
    CHECKCAST linc/cool/service/OrderService
    INVOKEVIRTUAL linc/cool/service/UserService.setOrderService (Llinc/cool/service/OrderService;)V
    RETURN
   L1
    LOCALVARIABLE this Llinc/cool/service/UserService; L0 L1 0
    MAXSTACK = 2
    MAXLOCALS = 2
}

可以看到UserService的字节码中有两个setOrderService方法

public setOrderService(Llinc/cool/service/OrderService;)V
public synthetic bridge setOrderService(Ljava/lang/Object;)V

并且都是存在@Autowired注解的,所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法

注入点进行注入

Spring在AutowiredAnnotationBeanPostProcessor#postProcessProperties方法中,会遍历所找到的注入点依次进行注入

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	// 找注入点(所有被@Autowired注解了的Field或Method) 此时已经可以直接从缓存中拿出来了
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
		// 给字段赋值,给方法参数赋值
		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;
}
/**
 * 注入
 */
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()) {
		// 遍历每个注入点进行依赖注入
		for (InjectedElement element : elementsToIterate) {
			element.inject(target, beanName, pvs);
		}
	}
}

字段注入

private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
    ...
    /**
     * 字段的注入
     */
    @Override
    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        // 这里没有进行判断Pvs有没有,和method有点区别
        Field field = (Field) this.member;
        Object value;
        if (this.cached) {
            // 对于原型Bean,第一次创建的时候,也找注入点,然后进行注入,此时cached为false,注入完了之后cached为true
            // 第二次创建的时候,先找注入点(此时会拿到缓存好的注入点),也就是AutowiredFieldElement对象,此时cache为true,也就进到此处了
            // 注入点内并没有缓存被注入的具体Bean对象,而是beanName,这样就能保证注入到不同的原型Bean对象
            try {
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            } catch (NoSuchBeanDefinitionException ex) {
                // Unexpected removal of target bean for cached argument -> re-resolve
                value = resolveFieldValue(field, bean, beanName);
            }
        } else {
            // 根据filed从BeanFactory中查到的匹配的Bean对象
            value = resolveFieldValue(field, bean, beanName);
        }
        // 反射给filed赋值
        if (value != null) {
            ReflectionUtils.makeAccessible(field);
            field.set(bean, value);
        }
    }
} 
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
    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();
    Object value;
    try {
        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    } catch (BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    }
    synchronized (this) {
        if (!this.cached) {
            Object cachedFieldValue = null;
            if (value != null || this.required) {
                cachedFieldValue = desc;
                // 注册一下beanName依赖了autowiredBeanNames,
                registerDependentBeans(beanName, autowiredBeanNames);
                if (autowiredBeanNames.size() == 1) {
                    String autowiredBeanName = autowiredBeanNames.iterator().next();
                    if (beanFactory.containsBean(autowiredBeanName) &&
                            beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                        // 构造一个ShortcutDependencyDescriptor作为缓存,保存了当前filed所匹配的autowiredBeanName,而不是对应的bean对象 (考虑原型bean)
                        cachedFieldValue = new ShortcutDependencyDescriptor(
                                desc, autowiredBeanName, field.getType());
                    }
                }
            }
            this.cachedFieldValue = cachedFieldValue;
            this.cached = true;
        }
    }
    return value;
}
  1. 遍历所有的AutowiredFieldElement对象
  2. 将对应的字段封装为DependencyDescriptor对象
  3. 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象
  4. 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortCutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该对象时,就可以拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
  5. 利用反射将结果赋值给对象的字段

Set方法注入

private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
    ...
    @Override
    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        // 如果pvs中已经有当前注入点的值了,则跳过注入 看属性描述器中对应属性的名字在不在pvs里,在就跳过
        if (checkPropertySkipping(pvs)) {
            return;
        }
        Method method = (Method) this.member;
        Object[] arguments;
        // 找值的
        // 第一次注入是没有缓存的
        if (this.cached) {
            try {
                arguments = resolveCachedArguments(beanName);
            } catch (NoSuchBeanDefinitionException ex) {
                // Unexpected removal of target bean for cached argument -> re-resolve
                arguments = resolveMethodArguments(method, bean, beanName);
            }
        } else {
            arguments = resolveMethodArguments(method, bean, beanName);
        }
        if (arguments != null) {
            try {
                ReflectionUtils.makeAccessible(method);
                method.invoke(bean, arguments);
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
    }
}
@Nullable
private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String b
    // 方法参数个数
    int argumentCount = method.getParameterCount();
    // 保存参数对应的Bean对象
    Object[] arguments = new Object[argumentCount];
    // 有几个方法参数就有几个依赖描述器
    DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
    Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
    Assert.state(beanFactory != null, "No BeanFactory available");
    TypeConverter typeConverter = beanFactory.getTypeConverter();
    // 遍历每个方法参数,找到匹配的bean对象
    for (int i = 0; i < arguments.length; i++) {
        MethodParameter methodParam = new MethodParameter(method, i);
        // this.required: 是不是一定要赋值
        DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.req
        currDesc.setContainingClass(bean.getClass());
        descriptors[i] = currDesc;
        try {
            Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBe
            if (arg == null && !this.required) {
                arguments = null;
                break;
            }
            arguments[i] = arg;
        } catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoin
        }
    }
    synchronized (this) {
        if (!this.cached) {
            if (arguments != null) {
                DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descripto
                registerDependentBeans(beanName, autowiredBeans);
                if (autowiredBeans.size() == argumentCount) {
                    Iterator<String> it = autowiredBeans.iterator();
                    Class<?>[] paramTypes = method.getParameterTypes();
                    for (int i = 0; i < paramTypes.length; i++) {
                        String autowiredBeanName = it.next();
                        if (beanFactory.containsBean(autowiredBeanName) &&
                                beanFactory.isTypeMatch(autowiredBeanName, paramTypes[
                            cachedMethodArguments[i] = new ShortcutDependencyDescripto
                                    descriptors[i], autowiredBeanName, paramTypes[i]);
                        }
                    }
                }
                this.cachedMethodArguments = cachedMethodArguments;
            } else {
                this.cachedMethodArguments = null;
            }
            this.cached = true;
        }
    }
    return arguments;
}
  1. 遍历所有的AutowiredMethodElement对象
  2. 遍历将对应的方法的参数,将每个参数封装成MethodParameter对象
  3. 将MethodParameter对象封装成DependencyDescriptor对象
  4. 调用BeanFactory#resolveDependency方法,传入DependencyDescriptor对象,进行依赖查找,摘到当前方法参数所匹配的Bean对象
  5. 将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建对象时,就可以直接拿缓存的结果对象beanName去BeanFactory中去拿Bean对象了,不用再次去进行查找
  6. 利用反射将找到的所有结果对象传给当前方法,并且执行

注入点注入流程图

注入点进行注入.png

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫吹过的柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值