Spring之依赖注入环节之@Autowired

注入模型下为什么可以给set属性来进行赋值

1、预备知识点:java属性描述器

首先来介绍一下java中的属性描述器。

首先来介绍一下什么叫做javabean?java认为一个bean中的属性是用private关键字修饰的,然后对其提供对应的getter/setter方法

如UserInfo类:

public class UserInfo {  

    private long userId;  
    private String userName;  
    private int age;  
    private String emailAddress;  

    public long getUserId() {  
        return userId;  
    }  

    public void setUserId(long userId) {  
        this.userId = userId;  
    }  

    public String getUserName() {  
        return userName;  
    }  

    public void setUserName(String userName) {  
        this.userName = userName;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public String getEmailAddress() {  
        return emailAddress;  
    }  

    public void setEmailAddress(String emailAddress) {  
        this.emailAddress = emailAddress;  
    }  
}

在类UserInfo中有属性userName,那我们可以通过getUserName, setUserName来得到其值或者设置新的值。通过getUserName/setUserName来访问userName属性,这就是默认的规则。Java JDK中提供了一套API用来访问某个属性的getter/setter方法,这就是内省。

PropertyDescriptor类:(属性描述器)
  PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:

   1. getPropertyType(),获得属性的Class对象;
      2. getReadMethod(),获得用于读取属性值的方法;
         3. getWriteMethod(),获得用于写入属性值的方法;
                   4. hashCode(),获取对象的哈希值;
                      5. setReadMethod(Method readMethod),设置用于读取属性值的方法;
                                6. setWriteMethod(Method writeMethod),设置用于写入属性值的方法。

示例代码:

public class Test {
    public static void main(String[] args) throws Exception {
        UserInfo userInfo = new UserInfo();
        // 加入说我现在已经知道了这个类中的属性
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor("userId", UserInfo.class);
        // 得到这个属性的get方法
        Method readMethod = propertyDescriptor.getReadMethod();
        // 得到这个属性的write方法
        Method writeMethod = propertyDescriptor.getWriteMethod();

        // 现在我想获取得到这个属性的值:
        Object invoke = readMethod.invoke(userInfo);
        System.out.println("通过getUserId来获取得到userId的值------->"+invoke);  // 0为默认值

        // 通过set方法来对其设置一个值
        writeMethod.invoke(userInfo, 666);
        invoke = readMethod.invoke(userInfo);
        System.out.println("通过getUserId来获取得到userId的值------->"+invoke);  // 0为默认值
    }
}

java认为作为一个javabean,应该有对应的private修饰的属性,private修饰的属性应该有对应的setter/getter方法。

那么java可以从Javabean来做一个推断,如果有private修饰的属性,那么就存在对应的setter/getter方法;

如果有对应的setter/getter方法,那么就应该存在着对应的属性。

所以spring中也利用了这个特性来做了一些处理。

举个例子:

public class UserInfo{
    private Integer age;
    public void setAge111(Integer age){
        this.age = age;
    }
}

如果说通过属性描述器来进行描述方法setAge111的话,那么java认为属性应该有一个叫age111的属性,但是实际上我们写的却是age.

这也是初学java对象的时候,java中的命名方式。

2、spring利用Javabean特性做事情

@Component
public class OrderService {}

正常的话,如果是没有添加任何注解的时候,这个类是不会成为Spring容器中的Bean的。

public class UserService {

    private OrderService orderService;

    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }

    public void test(){
        System.out.println("---------->"+orderService);
    }
}

在配置类中来配置,让UserService中的属性按照注入模型来进行注入。

也就是说UserService中的属性必须要提供对应的set方法,spring容器能够帮其从容器中来找到对应的需要的Bean的Name来进行注入。

@Configuration
@ComponentScan("com.guang.beandefinitaiontest.demo12")
public class AppConfig {
    
    @Bean(autowire= Autowire.BY_NAME)
    public UserService userService(){
        return new UserService();
    }
    
}

测试类:

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = newAnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);
        userService.test();
    }
}

控制台输出:

---------->com.guang.beandefinitaiontest.demo12.service.OrderService@fdefd3f

那么原理在哪里?如何来分析?

在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean中

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

对于UserService来说,对应的AutowireMode就是BY_NAME,那么肯定对应到这里来。

那么来看下是如何来进行处理的。

	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				registerDependentBean(propertyName, beanName);
			}
			else {
			}
		}
	}

在第一行代码中,会获取得到当前类的所有的get和set方法

	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set<String> result = new TreeSet<>();
		PropertyValues pvs = mbd.getPropertyValues();
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();
		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);
	}

但是如上所示,对于一个属性来说,必须要有set方法才会添加到result中来,然后将set方法来进行返回。

对于每个类来说,都有一个getClass方法,因为这里是Object类的方法,而这个对应的get方法,但是当前对象中可能没有class属性。

所以这里是来做了一个过滤。

问题一:为何要有这样的一个判断?

这里注意有几个判断:

如:BeanUtils.isSimpleProperty(pd.getPropertyType(),判断是否是简单类型

	public static boolean isSimpleValueType(Class<?> type) {
		return (Void.class != type && void.class != type &&
				(ClassUtils.isPrimitiveOrWrapper(type) ||
				Enum.class.isAssignableFrom(type) ||
				CharSequence.class.isAssignableFrom(type) ||
				Number.class.isAssignableFrom(type) ||
				Date.class.isAssignableFrom(type) ||
				Temporal.class.isAssignableFrom(type) ||
				URI.class == type ||
				URL.class == type ||
				Locale.class == type ||
				Class.class == type));
	}

如果说是简单类型,那么这里不会来进行注入。只有复杂类型才会来进行注入。

但是对于@Autowired来说,@Autowired是可以来进行注入的。

来做一个实验:

public class UserService {

    private OrderService orderService;


    private Date date;

    public void setDate(Date date) {
        this.date = date;
    }

    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }

    public void test(){
        System.out.println("---------->"+orderService);
        System.out.println("---------->"+date);
    }
}


@Configuration
@ComponentScan("com.guang.beandefinitaiontest.demo12")
public class AppConfig {

    @Bean
    public Date date(){
        return new Date();
    }

    @Bean(autowire= Autowire.BY_NAME)
    public UserService userService(){
        return new UserService();
    }

}

然后打印测试:

---------->com.guang.beandefinitaiontest.demo12.service.OrderService@a4102b8
---------->null

说明了使用注入模型的时候,简单类型是不会来进行注入的。

再比如:

!pvs.contains(pd.getName()

也就是说程序员如果对某个属性来进行了设置,那么这里来跳过。不会从容器中来给这个set方法对应的属性再来进行赋值了。

那么我来写个案例测试一下:

public class Person {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }


    public void test(){
        System.out.println("Person对应的test的值是:"+userService);
    }
}
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(AppConfig.class);
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(Person.class);
        genericBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
        UserService userService1 = new UserService();
        System.out.println("自动注入的userService的值是:"+userService1);
        genericBeanDefinition.getPropertyValues().add("userService",userService1);
        context.registerBeanDefinition("person",genericBeanDefinition);
        context.refresh();
        UserService userService = context.getBean(UserService.class);
        userService.test();
        System.out.println("容易中的userService的值是:"+userService);
        Person person = context.getBean(Person.class);
        person.test();
    }
}

手动的来对Person中的userService属性来进行注入,那么对于Person来说,就不需要来从容器中来进行查找得到对应的值了。

控制台输出:

自动注入的userService的值是:com.guang.beandefinitaiontest.demo12.service.UserService@26f67b76
---------->com.guang.beandefinitaiontest.demo12.service.OrderService@69930714
---------->null
容易中的userService的值是:com.guang.beandefinitaiontest.demo12.service.UserService@7a52f2a2
Person对应的test的值是:com.guang.beandefinitaiontest.demo12.service.UserService@26f67b76

但是一旦我将一些代码注释掉:

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(AppConfig.class);
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(Person.class);
        genericBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
/*        UserService userService1 = new UserService();
        System.out.println("自动注入的userService的值是:"+userService1);
        genericBeanDefinition.getPropertyValues().add("userService",userService1);*/
        context.registerBeanDefinition("person",genericBeanDefinition);
        context.refresh();
        UserService userService = context.getBean(UserService.class);
        userService.test();
        System.out.println("容易中的userService的值是:"+userService);
        Person person = context.getBean(Person.class);
        person.test();
    }
}

控制台打印:

---------->com.guang.beandefinitaiontest.demo12.service.OrderService@11dc3715
---------->null
容易中的userService的值是:com.guang.beandefinitaiontest.demo12.service.UserService@69930714
Person对应的test的值是:com.guang.beandefinitaiontest.demo12.service.UserService@69930714

那么就会是一样的。

然后对set方法对应的属性来进行赋值:

		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				registerDependentBean(propertyName, beanName);
			}
			else {
			}
		}

再次看到了熟悉的getBean方法,这里就是根据属性名称去容器中去查找,如果bean存在,就添加一下,然后注册

问题二:为什么这里找到了之后没有直接进行赋值?

其实对于@Autowired和@Resource来说,是直接来进行赋值的。但是这里没有来进行赋值。

但是中间是spring来进行依赖注入的点,是对@Autowired和@Resource注解来做处理的!

所以我觉得这里可能是要放置spring在进行@Autowired和@Resource的时候,放置破坏被注入了里面的值。

而保持让spring自己来注入的,后续会写个测试用例来测试一下。

最终是在哪里来进行赋值的呢?

是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

中的最后一行代码中来进行赋值的:

		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}

Spring中的依赖注入

spring中的依赖注入使用注解的话,大概是有两个注解。@Autowird和@Resource这两个。

那么分别来看一下,这两个注解都是如何来发挥作用的。

Spring内置处理器

因为在后面需要使用到来对@Autowired注解和@Resource注解做处理,Spring提前内置了处理器来进行处理。

org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)中

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, @Nullable Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                                                AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

然后在org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors中来实例化Bean,对应的步骤在org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry


Spring统一处理

无论是对于@Autowird和@Resource来说,这两个注解都是可以作用在类中的方法和属性上面的。

Spring在创建BeanDefinition对应的示例之后,开始来对进行属性填充:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
        processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
}

在这个地方,会有AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,这两个后置处理器来进行处理。

下面分别在下面来进行说明:

@Autowired

对于org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition来说,看下这里的逻辑:

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

首先来查找得到@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.
    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不是注入点,不会进行自动注入
                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 -> {

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

在这里来划分步骤:

首先判断,什么类型是不需要来进行注入的:

if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    return InjectionMetadata.EMPTY;
}

而这里的autowiredAnnotationTypes中的值是,@Autowired,@Value注解的

	public AutowiredAnnotationBeanPostProcessor() {
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

也就是说,如果类上、字段上和方法上都没有@Autowired,@Value注解,那么将不会来进行注入。也就是下面的环节将不会进来。

然后上面来遍历所有的属性和方法

遍历属性

// 遍历targetClass中的所有Field
ReflectionUtils.doWithLocalFields(targetClass, field -> {
    // field上是否存在@Autowired、@Value、@Inject中的其中一个
    MergedAnnotation<?> ann = findAutowiredAnnotation(field);
    if (ann != null) {
        // static filed不是注入点,不会进行自动注入
        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 -> {

    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);
            }
        }
        boolean required = determineRequiredStatus(ann);
        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
        currElements.add(new AutowiredMethodElement(method, required, pd));
    }
});

对于属性来说,添加的是AutowiredFieldElement,对于字段来说,添加的是AutowiredMethodElement。

从这里来看的话,最终都会保存到elements集合中来,而elements集合中的每个元素是InjectionMetadata.InjectedElement类型。

那么来看一下类结构发现:AutowiredMethodElement和AutowiredFieldElement都是继承自InjectedElement的。

public abstract static class InjectedElement {

   protected final Member member;

   protected final boolean isField;

   @Nullable
   protected final PropertyDescriptor pd;

   @Nullable
   protected volatile Boolean skip;
}

遍历父类中的属性和方法

然后在外层中加了一个do...while循环

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

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

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

那么继续来看一个东西,最终还会来找到父类中的加了@Autowired的属性和方法。

那么来测试一下:

@Component
public class Worker {}
public abstract class AbstractService {
	@Autowired
	private Worker worker;

	public void work(){
		System.out.println("worker的值是:"+worker);
	}
}
@Component
public class UserService extends AbstractService {
}
@Component
public class OrderService extends AbstractService {

}

写个测试类来进行测试:

public class Test {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		OrderService orderService = context.getBean(OrderService.class);
		orderService.work();
		UserService userService = context.getBean(UserService.class);
		userService.work();
	}
}

控制台输出:

worker的值是:com.gunag.ioc.demo1.service.Worker@1e643faf
worker的值是:com.gunag.ioc.demo1.service.Worker@1e643faf

注意的地方

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

这里是首先来从缓存中来进行查找,如果没有找到;那么真的去查找,查找完成之后,放入到缓存中去。

这样子的设计模式也是为了提高效率。

但是下面有一行代码:

public void checkConfigMembers(RootBeanDefinition beanDefinition) {
    Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
    for (InjectedElement element : this.injectedElements) {
        Member member = element.getMember();
        // 将Field或Method记录到BeanDefinition中的externallyManagedConfigMembers中,
        // 表示该Field或Method是BeanFactory外部管理的
        if (!beanDefinition.isExternallyManagedConfigMember(member)) {
            beanDefinition.registerExternallyManagedConfigMember(member);
            checkedElements.add(element);
        }
    }
    this.checkedElements = checkedElements;
}

这里的checkedElements和injectedElements之间的关系,我并不是特别清楚这里为什么要这样子来做。

依赖注入阶段

既然在postProcessMergedBeanDefinition阶段已经找到了注入点,那么接下来就应该来进行注入了。

在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean阶段开始来进行注入:

这次调用的是另外一个后置处理器:InstantiationAwareBeanPostProcessor的postProcessProperties方法

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 {
    // 这里拿到的是checkedElements
    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);
        }
    }
}

这里的注入阶段很简单,直接通过反射来进行操作:

针对AutowiredFieldElement来说:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

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

针对AutowiredMethodElement来说:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    // 如果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();
        }
    }
}

所以最终来到了最为关键的步骤:

value = resolveFieldValue(field, bean, beanName);
arguments = resolveMethodArguments(method, bean, beanName);

根据方法和字段来从容器中来找到对应的值,最终将会来到:

private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {
    int argumentCount = method.getParameterCount();
    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);

        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;
            }
            arguments[i] = arg;
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
        }
    }
    synchronized (this) {
        if (!this.cached) {
            if (arguments != null) {
                DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
                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[i])) {
                            cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
                                descriptors[i], autowiredBeanName, paramTypes[i]);
                        }
                    }
                }
                this.cachedMethodArguments = cachedMethodArguments;
            }
            else {
                this.cachedMethodArguments = null;
            }
            this.cached = true;
        }
    }
    return arguments;
}

那么这里又会有一个关键流程:

Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);

来到了这个方法:

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
                                @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    // 用来获取方法入参名字的
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());

    // 所需要的类型是Optional
    if (Optional.class == descriptor.getDependencyType()) {
        return createOptionalDependency(descriptor, requestingBeanName);
    }
    // 所需要的的类型是ObjectFactory,或ObjectProvider
    else if (ObjectFactory.class == descriptor.getDependencyType() ||
             ObjectProvider.class == descriptor.getDependencyType()) {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
    }
    else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
    }
    else {
        // 在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);

        if (result == null) {
            // descriptor表示某个属性或某个set方法
            // requestingBeanName表示正在进行依赖注入的Bean
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

@Lazy的作用

// 在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
    descriptor, requestingBeanName);

会执行到:

public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
    return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
}

org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver#isLazy

protected boolean isLazy(DependencyDescriptor descriptor) {
    for (Annotation ann : descriptor.getAnnotations()) {
        Lazy lazy = AnnotationUtils.getAnnotation(ann, Lazy.class);
        if (lazy != null && lazy.value()) {
            return true;
        }
    }
    MethodParameter methodParam = descriptor.getMethodParameter();
    if (methodParam != null) {
        Method method = methodParam.getMethod();
        if (method == null || void.class == method.getReturnType()) {
            Lazy lazy = AnnotationUtils.getAnnotation(methodParam.getAnnotatedElement(), Lazy.class);
            if (lazy != null && lazy.value()) {
                return true;
            }
        }
    }
    return false;
}

在这个阶段中,会来判断字段或者是方法有没有添加@Lazy注解。

如果添加了@Lazy注解,那么将会来创建一个代理对象:

protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
    BeanFactory beanFactory = getBeanFactory();
    Assert.state(beanFactory instanceof DefaultListableBeanFactory,
                 "BeanFactory needs to be a DefaultListableBeanFactory");
    final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;

    TargetSource ts = new TargetSource() {
        @Override
        public Class<?> getTargetClass() {
            return descriptor.getDependencyType();
        }
        @Override
        public boolean isStatic() {
            return false;
        }
        @Override
        public Object getTarget() {
            Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
            Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
            if (target == null) {
                Class<?> type = getTargetClass();
                if (Map.class == type) {
                    return Collections.emptyMap();
                }
                else if (List.class == type) {
                    return Collections.emptyList();
                }
                else if (Set.class == type || Collection.class == type) {
                    return Collections.emptySet();
                }
                throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
                                                        "Optional dependency not present for lazy injection point");
            }
            if (autowiredBeanNames != null) {
                for (String autowiredBeanName : autowiredBeanNames) {
                    if (dlbf.containsBean(autowiredBeanName)) {
                        dlbf.registerDependentBean(autowiredBeanName, beanName);
                    }
                }
            }
            return target;
        }
        @Override
        public void releaseTarget(Object target) {
        }
    };

    ProxyFactory pf = new ProxyFactory();
    pf.setTargetSource(ts);
    Class<?> dependencyType = descriptor.getDependencyType();
    if (dependencyType.isInterface()) {
        pf.addInterface(dependencyType);
    }
    return pf.getProxy(dlbf.getBeanClassLoader());
}

而当这个代理真正执行的时候,则会来执行getTarget方法,从容器中来获取得到容器中的对象。

举个例子说明一下:

@Component
public class Worker {}
@Component
public class OrderService extends AbstractService {
    
	@Autowired
	@Lazy
	private Worker worker;

	public void test(){
		worker.test();
	}
}

这里就相当于是在属性worker注入的时候,这里先赋值一个代理的对象;而当worker在调用test方法的时候,则是会去容器中找到真正的对应的Worker对象来调用。也就是对应的是上面的逻辑。

方法参数也是可以的。

这里也体现出来了延迟加载的一个作用。

最后一步

所以这里就是重点逻辑了。正常来说都是走最后一步路程:

result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

所以来看一下具体的详细的代码:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                                  @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        // 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }
		
        // 获取得到字段或者是方法上的类型
        Class<?> type = descriptor.getDependencyType();
        // 获取@Value所指定的值
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                // 占位符填充(${})
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                                     getMergedBeanDefinition(beanName) : null);
                // 解析Spring表达式(#{})
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            // 将value转化为descriptor所对应的类型
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            try {
                return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
            }
            catch (UnsupportedOperationException ex) {
                // A custom TypeConverter which does not support TypeDescriptor resolution...
                return (descriptor.getField() != null ?
                        converter.convertIfNecessary(value, type, descriptor.getField()) :
                        converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
            }
        }

        // 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }

        // 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            // required为true,抛异常
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        if (matchingBeans.size() > 1) {
            // 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                }
                else {
                    // In case of an optional Collection/Map, silently ignore a non-unique case:
                    // possibly it was meant to be an empty collection of multiple regular beans
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        // 记录匹配过的beanName
        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        // 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

@Value

其实对于@Value来说,最终需要从Envirement对象中取出来。可以有yml配置文件、JVM参数形式取出、properties文件取出。

但是取出来对应的值之后,需要利用类型转换器转换到对应的类型中去。

比如我们常常在配置文件中配置:

name:
  lig

只需要在@Value("${name}"),那么利用解析器可以拿到lig这个值。但是因为@Value可能是加载注解上的。

所以这个时候需要利用到类型转换器来发挥作用,也就是说进行类型转换。

所以这个时候,可能会出现ClassCastException异常。

这里也就是类型转换器的作用!非常有用,工具类要利用好。

甚至有的类型转换器可以将json转换成对象。

@Value("#{lig}"):如果这样子来写的话,表示的是去容器中找一个name为lig的bean来注入到当前bean中来。

所以这也是一种属性注入的方式。

// 将value转化为descriptor所对应的类型
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
    return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
    // A custom TypeConverter which does not support TypeDescriptor resolution...
    return (descriptor.getField() != null ?
            converter.convertIfNecessary(value, type, descriptor.getField()) :
            converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}

如果@Autowired作用对象是Map或者是List或者数组

// 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
    // 不为空就直接返回
    return multipleBeans;
}
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
                                    @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

    Class<?> type = descriptor.getDependencyType();

    if (descriptor instanceof StreamDependencyDescriptor) {
        // 找到type所匹配的所有bean
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }

        // 构造成一个stream
        Stream<Object> stream = matchingBeans.keySet().stream()
            .map(name -> descriptor.resolveCandidate(name, type, this))
            .filter(bean -> !(bean instanceof NullBean));

        // 排序
        if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
            stream = stream.sorted(adaptOrderComparator(matchingBeans));
        }
        return stream;
    }
    else if (type.isArray()) {
        // 得到数组元素的类型
        Class<?> componentType = type.getComponentType();
        ResolvableType resolvableType = descriptor.getResolvableType();
        Class<?> resolvedArrayType = resolvableType.resolve(type);
        if (resolvedArrayType != type) {
            componentType = resolvableType.getComponentType().resolve();
        }
        if (componentType == null) {
            return null;
        }
        // 根据数组元素类型找到所匹配的所有Bean
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
                                                                   new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        // 进行类型转化
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
        if (result instanceof Object[]) {
            Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
            if (comparator != null) {
                Arrays.sort((Object[]) result, comparator);
            }
        }
        return result;
    }
    else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
        Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
        if (elementType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
                                                                   new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        Object result = converter.convertIfNecessary(matchingBeans.values(), type);
        if (result instanceof List) {
            if (((List<?>) result).size() > 1) {
                Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
                if (comparator != null) {
                    ((List<?>) result).sort(comparator);
                }
            }
        }
        return result;
    }
    else if (Map.class == type) {
        ResolvableType mapType = descriptor.getResolvableType().asMap();
        Class<?> keyType = mapType.resolveGeneric(0);
        // 如果Map的key不是String
        if (String.class != keyType) {
            return null;
        }
        Class<?> valueType = mapType.resolveGeneric(1);
        if (valueType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
                                                                   new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        return matchingBeans;
    }
    else {
        return null;
    }
}

可以看到这里还是支持这种集合形式的。

正常是单个的情况

使用@Autowired注解来找的时候,首先通过类型来查找

// 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
    // required为true,抛异常
    if (isRequired(descriptor)) {
        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    }
    return null;
}

这里根据类型找到了单个类型的多个bean,那么下面将会来进行判断。

但是如果利用@Autowired注解来进行查找的时候,如果说没有找到,但是@Autowired中的注解属性Required又是默认为true的,找不到这里就会来报错。如果Required为false的话,那么这里就直接返回null

然后接着来判断:

String autowiredBeanName;
Object instanceCandidate;

if (matchingBeans.size() > 1) {
    // 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    if (autowiredBeanName == null) {
        if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
            return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
        }
        else {
            // In case of an optional Collection/Map, silently ignore a non-unique case:
            // possibly it was meant to be an empty collection of multiple regular beans
            // (before 4.3 in particular when we didn't even look for collection beans).
            return null;
        }
    }
    instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
    // 不是多个,又不为空,那么肯定就只有一个
    // 确定只有一个匹配
    // We have exactly one match.
    Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
    autowiredBeanName = entry.getKey();
    instanceCandidate = entry.getValue();
}

@Autowired根据类型匹配找到多个,又该如何处理

if (matchingBeans.size() > 1) {
    // 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    if (autowiredBeanName == null) {
        if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
            return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
        }
        else {
            // In case of an optional Collection/Map, silently ignore a non-unique case:
            // possibly it was meant to be an empty collection of multiple regular beans
            // (before 4.3 in particular when we didn't even look for collection beans).
            return null;
        }
    }
    instanceCandidate = matchingBeans.get(autowiredBeanName);
}

那么看一下重要方法:

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
    Class<?> requiredType = descriptor.getDependencyType();
    // candidates表示根据类型所找到的多个Bean,判断这些Bean中是否有一个是@Primary的
    String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
    if (primaryCandidate != null) {
        return primaryCandidate;
    }

    // 取优先级最高的Bean
    String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
    if (priorityCandidate != null) {
        return priorityCandidate;
    }

    // Fallback
    // 匹配descriptor的名字,要么是字段的名字,要么是set方法入参的名字
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateName = entry.getKey();
        Object beanInstance = entry.getValue();

        // resolvableDependencies记录了某个类型对应某个Bean,启动Spring时会进行设置,比如BeanFactory.class对应			    // BeanFactory实例
        // 注意:如果是Spring自己的byType,descriptor.getDependencyName()将返回空,只有是@Autowired才会方法属性名或方法		    // 参数名
        if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
            matchesBeanName(candidateName, descriptor.getDependencyName())) {
            return candidateName;
        }
    }
    return null;
}

第一个判断,根据类型找到多个bean的时候,优先找加了@Primary注解的bean。

// candidates表示根据类型所找到的多个Bean,判断这些Bean中是否有一个是@Primary的
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
    return primaryCandidate;
}
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    String primaryBeanName = null;
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateBeanName = entry.getKey();
        Object beanInstance = entry.getValue();
        if (isPrimary(candidateBeanName, beanInstance)) {
            if (primaryBeanName != null) {
                boolean candidateLocal = containsBeanDefinition(candidateBeanName);
                boolean primaryLocal = containsBeanDefinition(primaryBeanName);
                // 如果有多个@primary,这里报错
                if (candidateLocal && primaryLocal) {
                    throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                                                              "more than one 'primary' bean found among candidates: " + candidates.keySet());
                }
                else if (candidateLocal) {
                    primaryBeanName = candidateBeanName;
                }
            }
            else {
                primaryBeanName = candidateBeanName;
            }
        }
    }
    return primaryBeanName;
}

第二个判断,判断是否在类上加了@Priority注解

// 取优先级最高的Bean
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
    return priorityCandidate;
}

看下具体实现:

protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    String highestPriorityBeanName = null;
    Integer highestPriority = null;
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateBeanName = entry.getKey();
        Object beanInstance = entry.getValue();
        if (beanInstance != null) {
            Integer candidatePriority = getPriority(beanInstance);
            if (candidatePriority != null) {
                if (highestPriorityBeanName != null) {
                    if (candidatePriority.equals(highestPriority)) {
                        throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                                                                  "Multiple beans found with the same priority ('" + highestPriority +
                                                                  "') among candidates: " + candidates.keySet());
                    }
                    else if (candidatePriority < highestPriority) {
                        highestPriorityBeanName = candidateBeanName;
                        highestPriority = candidatePriority;
                    }
                }
                else {
                    highestPriorityBeanName = candidateBeanName;
                    highestPriority = candidatePriority;
                }
            }
        }
    }
    return highestPriorityBeanName;
}

如果有多个类型的Bean,需要调整一下优先级。不然优先级如果相同,那么会报错。

在@Priority中的数字越小,优先级越高。

第三个判断,根据bean的名称来进行判断

// Fallback
// 匹配descriptor的名字,要么是字段的名字,要么是set方法入参的名字
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
    String candidateName = entry.getKey();
    Object beanInstance = entry.getValue();

    // resolvableDependencies记录了某个类型对应某个Bean,启动Spring时会进行设置,比如BeanFactory.class对应BeanFactory实	 // 例
    // 注意:如果是Spring自己的byType,descriptor.getDependencyName()将返回空,只有是@Autowired才会方法属性名或方法参数名
    if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
        matchesBeanName(candidateName, descriptor.getDependencyName())) {
        return candidateName;
    }
}

如果没有加@Primary和@Priority,才会根据名字来进行注入。

问题:如果有优先级的存在,那么优先级比较低的如何处理?

如上面所示,如果一个类有两个Bean,如A和B,但是因为A的优先级比较高,B的优先级比较低。

那么在注入的时候都是使用的是A,那么B可能在当前注入阶段中使用不到。所以又该如何来进行处理?

spring中的处理很智能:

// 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
if (instanceCandidate instanceof Class) {
    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
    if (isRequired(descriptor)) {
        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    }
    result = null;
}

如果说,当前根据类型查找出来的(BeanDefinition中的beanClass),如果类型是Class类型的,那么表示还没有进行bean的生命周期;

那么在这里,将会来走bean的生命周期;如果对应的是null,还要判断required是否为true,如果为true,但是返回的是null,那么直接报错;如果required是FALSE,那么这里最终返回的是null。

注入完成之后,直接将最终的进行返回。

根据类型找到所有的Bean的原理

这里是一个核心方法

// 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

首先应该自己来思考一下,根据类型来找bean的话,可以从哪里来找。上面也提到了一种,根据BeanDefinition中的beanclass来查找。

我总结一下:1、单例池;2、BeanDefinition;3、FactoryBean中的getObjectType方法;

那么看看spring是如何来做到的?

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

首先根据类型来找到匹配的所有的Bean的名称。看看如何来查找到的

public static String[] beanNamesForTypeIncludingAncestors(
    ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {

    Assert.notNull(lbf, "ListableBeanFactory must not be null");
    // 从本容器中找
    String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
    // 从父容器找并放入result
    if (lbf instanceof HierarchicalBeanFactory) {
        HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
        if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
            String[] parentResult = beanNamesForTypeIncludingAncestors(
                (ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
            result = mergeNamesWithParent(result, parentResult, hbf);
        }
    }
    return result;
}

从父子容器中来根据类型查找,如果只需要看一下根据类型来进行查找的方式:

public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    // 如果没有冻结,就根据类型去BeanFactory找,如果冻结了,可能就跳过这个if然后去缓存中去拿了
    if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
        return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
    }

    // 把当前类型所匹配的beanName缓存起来
    Map<Class<?>, String[]> cache =
        (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
    String[] resolvedBeanNames = cache.get(type);
    if (resolvedBeanNames != null) {
        return resolvedBeanNames;
    }
    resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
    if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
        cache.put(type, resolvedBeanNames);
    }
    return resolvedBeanNames;
}

看一个重要参数:includeNonSingletons,是否包含非单例的。

如果includeNonSingletons为true,那么就会找到所有的Definition;如果为FALSE,那么表示的是只要单例bean;

可以看到有两个对应类型的集合分别来进行存储:allBeanNamesByType和singletonBeanNamesByType

所以来到了核心方法:

resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);

看下具体实现:

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    List<String> result = new ArrayList<>();

    // Check all bean definitions.
    // 遍历所有的BeanDefinitions
    for (String beanName : this.beanDefinitionNames) {
        // Only consider bean as eligible if the bean name is not defined as alias for some other bean.
        if (!isAlias(beanName)) {
            try {
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // Only check bean definition if it is complete.
                // 判断mbd允不允许获取对应类型
                // 首先mdb不能是抽象的,然后allowEagerInit为true,则直接去推测mdb的类型,并进行匹配
                // 如果allowEagerInit为false,那就继续判断,如果mdb还没有加载类并且是懒加载的并且不允许提前加载类,那mbd不能用来进行匹配(因为不允许提前加载类,只能在此mdb自己去创建bean对象时才能去创建类)
                // 如果allowEagerInit为false,并且mbd已经加载类了,或者是非懒加载的,或者允许提前加载类,并且不用必须提前初始化才能获取类型,那么就可以去进行匹配了
                // 这个条件有点复杂,但是如果只考虑大部分流程,则可以忽略这个判断,因为allowEagerInit传进来的基本上都是true
                if (!mbd.isAbstract() && (allowEagerInit ||
(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&!requiresEagerInitForType(mbd.getFactoryBeanName()))) {

                    boolean isFactoryBean = isFactoryBean(beanName, mbd);
                    BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
                    boolean matchFound = false;
                    boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
                    boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());

                    // 当前BeanDefinition不是FactoryBean,就是普通Bean
                    if (!isFactoryBean) {
                        // 在筛选Bean时,如果仅仅只包括单例,但是beanName对应的又不是单例,则忽略
                        if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                    }
                    else {
                        if (includeNonSingletons || isNonLazyDecorated ||
                            (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                        if (!matchFound) {
                            // In case of FactoryBean, try to match FactoryBean instance itself next.
                            beanName = FACTORY_BEAN_PREFIX + beanName;
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                    }
                    if (matchFound) {
                        result.add(beanName);
                    }
                }
            }
			...........................

    return StringUtils.toStringArray(result);
}

首先来遍历容器中所有的BeanDefinition的名称集合,然后判断是否是factorybean。接下来将会对是factorybean和不是factorybean的BeanDefinition来做处理

首先来一下判断逻辑isTypeMatch:

这里的代码太长,主要还是上面的三种逻辑来进行判断的:单例池、BeanDefinition中的beanClass还有FactoryBean中的getType来进行判断和spring找的类型是否是匹配的。

还有spring内置的几个对应的类型存在resolvableDependencies集合中:

// 根据类型从resolvableDependencies中匹配Bean,resolvableDependencies中存放的是类型:Bean对象,比如BeanFactory.class:BeanFactory对象,在Spring启动时设置
for (Map.Entry<Class<?>, 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);
    }
}

如果是自己注入自己的情况,并且找到了当前类型的bean,那么会将自己过滤掉,将在外面注入的添加进来result集合中来。

这个不符合自己只是其中的一个条件,还有另外一个条件,用来判断是否能够满足注入。

也就是isAutowireCandidate这个条件,也就是说虽然说配置了,但是不满足依赖注入条件。

如下所示:

	/**
	 * 不会自动注入
	 * @return
	 */
	@Bean(autowireCandidate = false)
	public OrderService orderService1(){
		return new OrderService();
	}

	@Bean
	public OrderService orderService2(){
		return new OrderService();
	}
public class OrderService  implements BeanNameAware {

	private String beanBame;


	@Override
	public void setBeanName(String name) {
		beanBame =name;
	}

	public void name(){
		System.out.println(beanBame);
	}
}

控制台打印:

orderService3

这里也是一种判断方式。

但是如果将autowireCandidate = false去掉,那么就又会报错了。因为按照类型找到了多个,根据名称找,发现没有匹配的,报错。

判断能够进行注入

我们从上面能够看到,对于isAutowireCandidate这个判断来说,这里也是分为了好几个步骤来进行区分的。

首先调用:

  • org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate
  • org.springframework.beans.factory.support.GenericTypeAwareAutowireCandidateResolver#isAutowireCandidate;
  • org.springframework.beans.factory.support.SimpleAutowireCandidateResolver#isAutowireCandidate

分别来介绍一下:

  • 1、第一种是用来处理@Qulifier注解的;
  • 2、第二种是用来处理泛型的;
  • 3、第三种就是根据BeanDefinition中的属性判断的;

如果父类中的判断不满足,那么子类也不满足。所以说优先级顺序是倒置过来的。

但是如果父类的满足了,子类再来判断自己的条件;

刚刚使用注解来添加的就是第三种;第二种泛型的几乎用不上,不需要管;但是第三种是可以采用的;

泛型判断是否能够注入

找到类后,需要循环对每个beanName是否能够来进行注入。

首先判断的是是否能够被依赖注入;

然后判断泛型对应的类能够被找到;

最终通过@Qulified指定的名称来找对应的名称;

下面来看下泛型的。

public class BaseService<O, S> {

	@Autowired
	O o;

	@Autowired
	S s;

	public void helo(){
		System.out.println("o的值是:"+o);
		System.out.println("s的值是:"+s);
	}
}
@Component
public class OrderService {
}

@Component
public class StockService {
}

public class BaseService<O, S> {

	@Autowired
	O o;

	@Autowired
	S s;

	public void helo(){
		System.out.println("o的值是:"+o);
		System.out.println("s的值是:"+s);
	}
}

@Component
public class UserService extends BaseService<OrderService,StockService> {

	public void test(){
		helo();
	}
}

测试类:

public class Test {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		context.getBean(UserService.class).test();
	}
}
o的值是:com.gunag.ioc.demo2.service.impl.OrderService@36d64342
s的值是:com.gunag.ioc.demo2.service.impl.StockService@39ba5a14

上面的使用到了泛型,就是org.springframework.beans.factory.support.GenericTypeAwareAutowireCandidateResolver#isAutowireCandidate;来进行处理的。

具体的原理是使用了JDK的反射确定泛型的值,从而来确定真正依赖的值是什么。不再来深究这里的原理了,过于底层了。

那么我们看一下@Qualifier能够处理的:

public class OrderService implements BeanNameAware {

	private String name;

	@Override
	public void setBeanName(String name) {
		this.name = name;
	}

	public void test(){
		System.out.println("beanName is ---->"+name);
	}
}

配置类:

@Configuration
@ComponentScan("com.gunag.ioc.demo2")
public class AppConfig {


	@Bean
	@Qualifier("o1")
	public OrderService orderService1(){
		return new OrderService();
	}

	@Bean
	@Qualifier("o2")
	public OrderService orderService2(){
		return new OrderService();
	}

}

服务类:

@Component
public class PersonService {


	@Autowired
	@Qualifier("o1")
	private OrderService orderService;

	public void test(){
		orderService.test();
	}
}

控制台打印:

public class Test {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		context.getBean(PersonService.class).test();
	}
}

在修改@Qualifier("o1")中的值的时候,可以看到控制台显示也是不同的。

// 为空要么是真的没有匹配的,要么是匹配的自己
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;

依赖注入缓存阶段

对应的是下面这行代码:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    if (this.cached) {
        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 {
        value = resolveFieldValue(field, bean, beanName);
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

这里为什么会有缓存呢?对于一个Bean来说,依赖注入阶段,我们通过理解的是只会来注入一次,这里的缓存难道会存在注入多次的情况来使用到这个缓存吗?

那么这个时候应该想要下面情况呢?

@Component
public class UserService {

    @Autowired
    private OrderService orderService;

    @Autowired
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }
}

首先加了@Autowired的属性和方法是两个注入点,但是并没有使用到缓存。

因为对于字段和方法来说:

	private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

		private final boolean required;

		private volatile boolean cached;
    }
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {

    private final boolean required;

    private volatile boolean cached;
}

这是两个cached字段的值,所以这两个的值是不同的。

那么这里的缓存表示的就不是这个意思了。那么观察一下缓存中做了什么事情:

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

传入的是beanName,而不是真实的bean。所以这就很奇怪。

所以这个时候应该考虑到不是单例bean的问题了,而可能是其他类型的bean,比如说原型bean。

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class OrderService {

}

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class UserService {

    @Autowired
    private OrderService orderService;

    @Autowired
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig13.class);
        UserService userService = context.getBean(UserService.class);
        UserService userService1 = context.getBean(UserService.class);
    }
}

打上断点,发现果然是执行到了这里。第二次调用的时候这里会来走缓存。

这里也发现了spring为什么在注册时候要来设计一下缓存,让原型bean也来走这一步的逻辑!

但是这里也突然想到了,为什么要调用getBean方法,让原型bean来进行实例化了。

走缓存的时候存的时候是利用ShortcutDependencyDescriptor,那么取的时候也需要利用到ShortcutDependencyDescriptor来取。

@Autowired流程图总结

首先在利用@Autowired注解来进行注入的时候,发现了几个关键方法。下面来总结一下对应的流程。

1、beanFactory.resolveDependency

2、findAutowireCandidates

来总结一下这两个方法的流程。因为findAutowireCandidates是在resolveDependency内部的,所以先来总结一下findAutowireCandidates方法。

findAutowireCandidates方法

先按照类型来进行查找beanName,然后根据beanName找到具体的类型:

@Autowired具体的细节流程是:

DefaultListableBeanFactoryresolveDependency()

posted @ 2022-08-27 09:59  雩娄的木子  阅读(47)  评论(0编辑  收藏  举报