Spring-依赖注入findAutowireCandidates源码实现

findAutowireCandidates()实现

1、找出BeanFactory中类型为type的所有的Bean的名字,根据BeanDefinition就能判断和当前type是不是匹配,不用生成Bean对象

2、把resolvableDependencies中key为type的对象找出来并添加到result中

3、遍历根据type找出的beanName,判断当前beanName对应的Bean是不是能够被自动注入

4、先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果为false,表示不能用来进行自动注入,如果为true则继续进行判断

5、判断当前type是不是泛型,如果是泛型是会把容器中所有的beanName找出来的,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么则继续判断

6、如果当前DependencyDescriptor上存在@Qualifier注解,那么则要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等则匹配

7、经过上述验证之后,当前beanName才能成为一个可注入的,添加到result中

/**
 * Find bean instances that match the required type.
 * Called during autowiring for the specified bean.
 * @param beanName the name of the bean that is about to be wired
 * @param requiredType the actual type of bean to look for
 * (may be an array component type or collection element type)
 * @param descriptor the descriptor of the dependency to resolve
 * @return a Map of candidate names and candidate instances that match
 * the required type (never {@code null})
 * @throws BeansException in case of errors
 * @see #autowireByType
 * @see #autowireConstructor
 */
protected Map findAutowireCandidates(
		@Nullable String beanName, Class requiredType, DependencyDescriptor descriptor) {

	// 从BeanFactory中找出和requiredType所匹配的beanName,仅仅是beanName,这些bean不一定经过了实例化,只有到最终确定某个Bean了,如果这个Bean还没有实例化才会真正进行实例化
	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
	Map result = CollectionUtils.newLinkedHashMap(candidateNames.length);

	// 根据类型从resolvableDependencies中匹配Bean,resolvableDependencies中存放的是类型:Bean对象,比如BeanFactory.class:BeanFactory对象,在Spring启动时设置
	for (Map.Entry, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
		Class autowiringType = classObjectEntry.getKey();
		if (autowiringType.isAssignableFrom(requiredType)) {
			Object autowiringValue = classObjectEntry.getValue();
			autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);

			if (requiredType.isInstance(autowiringValue)) {
				result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
				break;
			}
		}
	}


	for (String candidate : candidateNames) {
		// 如果不是自己,则判断该candidate到底能不能用来进行自动注入
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}

	// 为空要么是真的没有匹配的,要么是匹配的自己
	if (result.isEmpty()) {
		// 需要匹配的类型是不是Map、数组之类的
		boolean multiple = indicatesMultipleBeans(requiredType);
		// Consider fallback matches if the first pass failed to find anything...
		DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
		for (String candidate : candidateNames) {
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
					(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}

		// 匹配的是自己,被自己添加到result中
		if (result.isEmpty() && !multiple) {
			// Consider self references as a final pass...
			// but in the case of a dependency collection, not the very same bean itself.
			for (String candidate : candidateNames) {
				if (isSelfReference(beanName, candidate) &&
						(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
						isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
		}
	}
	return result;
}

依赖注入中泛型注入的实现

首先在Java反射中,有一个Type接口,表示类型,具体分类为:

1、raw types:也就是普通Class

2、parameterized types:对应ParameterizedType接口,泛型类型

3、array types:对应GenericArrayType,泛型数组

4、type variables:对应TypeVariable接口,表示类型变量,也就是所定义的泛型,比如T、K

5、primitive types:基本类型,int、boolean

public class TypeTest
{
    private int i;
    
    private Integer it;
    
    private int[] iarray;
    
    private List list;
    
    private List slist;
    
    private List tlist;
    
    private T t;
    
    private T[] tarray;
    
    public static void main(String[] args) throws NoSuchFieldException
    {
        test(TypeTest.class.getDeclaredField("i"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("it"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("iarray"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("list"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("slist"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("tlist"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("t"));
        System.out.println("=======");
        test(TypeTest.class.getDeclaredField("tarray"));
        
    }
    
    public static void test(Field field)
    {
        if (field.getType().isPrimitive())
        {
            System.out.println(field.getName() + "是基本数据类型");
        }
        else
        {
            System.out.println(field.getName() + "不是基本数据类型");
        }
        
        if (field.getGenericType() instanceof ParameterizedType)
        {
            System.out.println(field.getName() + "是泛型类型");
        }
        else
        {
            System.out.println(field.getName() + "不是泛型类型");
        }
        
        if (field.getType().isArray())
        {
            System.out.println(field.getName() + "是普通数组");
        }
        else
        {
            System.out.println(field.getName() + "不是普通数组");
        }
        
        if (field.getGenericType() instanceof GenericArrayType)
        {
            System.out.println(field.getName() + "是泛型数组");
        }
        else
        {
            System.out.println(field.getName() + "不是泛型数组");
        }
        
        if (field.getGenericType() instanceof TypeVariable)
        {
            System.out.println(field.getName() + "是泛型变量");
        }
        else
        {
            System.out.println(field.getName() + "不是泛型变量");
        }
    }
}

Spring中注入点是泛型的处理:

@Component
public class UserService extends BaseService 
{
    public void test() 
    {
        System.out.println(o);
    }
}

public class BaseService 
{
    @Autowired
    protected O o;

    @Autowired
    protected S s;
}

1、Spring扫描时发现UserService是一个Bean

2、取出注入点,也就是BaseService中的两个属性o、s

3、按注入点类型进行注入,发现o和s都是泛型,所以Spring需要确定o和s的具体类型

4、当前正在创建的是UserService的Bean,所以可以通过下面这行代码获取到具体的泛型信息

userService.getClass().getGenericSuperclass().getTypeName()
返回:
com.gax.service.BaseService

5、获取UserService的父类BaseService的泛型变量

for (TypeVariable> typeParameter : userService.getClass().getSuperclass().getTypeParameters()) 
{
    System._out_.println(typeParameter.getName()); 
}

6、根据第4、5步,可以知道o对应的具体就是OrderService,s对应的具体类型就是StockService

7、调用oField.getGenericType()就知道当前field使用的是哪个泛型,得到具体类型

@Qualifier的使用

定义两个注解:

@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("random")
public @interface Random {
}

@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("roundRobin")
public @interface RoundRobin {
}

定义一个接口和两个实现类,表示负载均衡:

public interface LoadBalance 
{
    String select();
}

@Component
@Random
public class RandomStrategy implements LoadBalance 
{
    @Override
    public String select() 
    {
        return null;
    }
}

@Component
@RoundRobin
public class RoundRobinStrategy implements LoadBalance 
{
    @Override
    public String select() 
    {
        return null;
    }
}

使用:

@Component
public class UserService  
{
    @Autowired
    @RoundRobin
    private LoadBalance loadBalance;

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

你可能感兴趣的:(spring,java)