spring依赖查找、依赖注入深入学习及源码分析

文章目录

一、依赖查找

1、单一类型依赖查找(接口 - BeanFactory)

用于查找已知类型或名称的Bean对象。

根据Bean名称查找

// getBean(String) 根据名称获取bean
Object bean = beanfactory.getBean("beanName");

// Spring 2.5 覆盖默认参数:getBean(String,Object...)
Object bean = beanfactory.getBean("beanName", args ...);

根据Bean类型实时查找

// Spring 3.0 getBean(Class)
User bean = beanfactory.getBean(User.class);

// Spring 4.1 覆盖默认参数:getBean(Class,Object...)
User bean = beanfactory.getBean(User.class, args ...);

根据Bean类型延迟查找(Spring 5.1)

// getBeanProvider(Class)
ObjectProvider<User> objectProvider = applicationContext.getBeanProvider(User.class);
User bean = beanfactory.getObject();
// getBeanProvider(ResolvableType)

根据Bean名称+类型查找

// getBean(String,Class)
User bean = beanfactory.getBean("beanName", User.class);

2、集合类型依赖查找(接口 - ListableBeanFactory)

查找已知类型多个Bean的集合。

ListableBeanFactory接口继承了BeanFactory接口,在原来的BeanFactory接口的基础上做了增强。

对于集合类型依赖查找,通过ListableBeanFactory#getBeanNamesForType 和ListableBeanFactory#getBeansForType,两个依赖查找方法,前者不会强制bean的初始化,而是通过BeanDefinition和FactoryBean的getClassType进行判断;后者会强制Bean的初始化。

根据Bean类型查找

// 获取同类型 Bean 名称列表 getBeanNamesForType(Class)
String[] beans = factory.getBeanNamesForType(User.class);

// 获取同类型 Bean 名称列表 Spring 4.2 
getBeanNamesForType(ResolvableType)

// 获取同类型 Bean 实例列表 getBeansOfType(Class) 以及重载方法
Map<String, User> usersMap = context.getBeansOfType(User.class);

通过注解类型查找 Spring 4.0

可以查找到标注了某注解的bean。

// 获取标注类型 Bean 名称列表
getBeanNamesForAnnotation(Class<? extends Annotation>)

// 获取标注类型 Bean 实例列表
getBeansWithAnnotation(Class<? extends Annotation>)

// 获取指定名称 + 标注类型 Bean 实例
findAnnotationOnBean(String,Class<? extends Annotation>)

3、层次性依赖查找(接口 - HierarchicalBeanFactory)

层次性容器使用场景

容器的层次关系主要的目的是实现 Bean 复用,假设一个应用存在一个 Root ApplicationContext,内部的 Bean 来自于一个 jar 包,那么,这个jar 包可能被两个不同的 Servlet 应用使用,这时,ServletContext A 和 ServletContext B 同时复用了这个 parent ApplicationContext,而它自己也有 ApplicationContext,这也是 Spring Web MVC 所涉及的应用上下文架构。

层次性依赖查找实例

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 层次性依赖查找示例
 */
public class HierarchicalDependencyLookupDemo {
    
    

    public static void main(String[] args) {
    
    
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 将当前类 ObjectProviderDemo 作为配置类(Configuration Class)
        applicationContext.register(ObjectProviderDemo.class); // 不包含user

        // 1. 获取 HierarchicalBeanFactory <- ConfigurableBeanFactory(子) <- ConfigurableListableBeanFactory(子)
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
//        System.out.println("当前 BeanFactory 的 Parent BeanFactory : " + beanFactory.getParentBeanFactory());

        // 2. 设置 Parent BeanFactory
        HierarchicalBeanFactory parentBeanFactory = createParentBeanFactory(); // 包含user
        beanFactory.setParentBeanFactory(parentBeanFactory);
//        System.out.println("当前 BeanFactory 的 Parent BeanFactory : " + beanFactory.getParentBeanFactory());

        // 查询LocalBean
        displayContainsLocalBean(beanFactory, "user");
        displayContainsLocalBean(parentBeanFactory, "user");

        // 通过递归查询Bean
        displayContainsBean(beanFactory, "user");
        displayContainsBean(parentBeanFactory, "user");

        // 启动应用上下文
        applicationContext.refresh();

        // 关闭应用上下文
        applicationContext.close();

    }

    private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {
    
    
        System.out.printf("当前 BeanFactory[%s] 是否包含 Bean[name : %s] : %s\n", beanFactory, beanName,
                containsBean(beanFactory, beanName));
    }

    /**
     * 双亲委派方式,优先查找父类的Bean
     */
    private static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
    
    
        BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
        if (parentBeanFactory instanceof HierarchicalBeanFactory) {
    
    
            HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);
            if (containsBean(parentHierarchicalBeanFactory, beanName)) {
    
    
                return true;
            }
        }
        return beanFactory.containsLocalBean(beanName);
    }

    private static void displayContainsLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {
    
    
        System.out.printf("当前 BeanFactory[%s] 是否包含 Local Bean[name : %s] : %s\n", beanFactory, beanName,
                beanFactory.containsLocalBean(beanName));
    }

    private static ConfigurableListableBeanFactory createParentBeanFactory() {
    
    
        // 创建 BeanFactory 容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        // XML 配置文件 ClassPath 路径
        String location = "classpath:/META-INF/dependency-lookup-context.xml";
        // 加载配置
        reader.loadBeanDefinitions(location);
        return beanFactory;
    }

}

使用BeanFactoryUtils查找Bean

  • 单一类型:BeanFactoryUtils#beanOfType
  • 集合类型:BeanFactoryUtils#beansOfTypeIncludingAncestors
  • 根据 Java 注解查找名称列表:BeanFactoryUtils#beanNamesForTypeIncludingAncestors
// org.springframework.beans.factory.BeanFactoryUtils#beansOfTypeIncludingAncestors(org.springframework.beans.factory.ListableBeanFactory, java.lang.Class<T>)
// 也是递归,从父容器查找到子容器
public static <T> Map<String, T> beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)
		throws BeansException {
    
    

	Assert.notNull(lbf, "ListableBeanFactory must not be null");
	Map<String, T> result = new LinkedHashMap<>(4);
	result.putAll(lbf.getBeansOfType(type));
	if (lbf instanceof HierarchicalBeanFactory) {
    
    
		HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
		if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
    
    
			Map<String, T> parentResult = beansOfTypeIncludingAncestors(
					(ListableBeanFactory) hbf.getParentBeanFactory(), type);
			parentResult.forEach((beanName, beanInstance) -> {
    
    
				if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
    
     // 有相同的bean优先使用父容器的
					result.put(beanName, beanInstance);
				}
			});
		}
	}
	return result;
}

4、延迟依赖查找(接口 - ObjectFactory)

延迟查找并非是Bean的延迟加载,跟@Lazy是两码事,延迟指的就是查找的时候并没有查找到想要查找的那个bean而是查找到了,objectFactory或者objectProvider。并且Provider还比Factory多了能查找出多个的功能。ObjectProvider#getxxx 方法 底层还是通过BeanFactory来进行依赖查找的,但是在进行依赖查找前,可以制定以下规则,比如Bean找到后,再设置额外的属性,完成一些用户的自定义需求;Bean没有找到,该如何处理。

理解什么是延迟依赖查找

延迟查找,我个人认为主要是给架构开发者使用的。非常典型的一个使用场景,就是SpringBoot里的自动配置,可以看看LettuceConnectionConfiguration这个类,这个类用于创建RedisClient。显然,RedisClient的创建是要根据用户的需求来创建的。

有些属性是必须的,可以在配置文件里配置,比如ip,port这种。Lettuce在创建RedisClient的时候,会从配置文件里读取这些数据来创建RedisClient。

但有些属性是非必须的,而且不能在配置文件里配置,比如开启读写分离,RedisClient在Lettuce内部,是通过一个Builder来创建的,如果要开启读写分离,这需要你在这个Builder在执行build的过程中,额外加一行:clientConfigurationBuilder.readFrom(ReadFrom.REPLICA);

问题就在这里,怎么让业务开发人员把这行代码加入到其内部的build流程中?这个问题,一种比较常见的思路,是使用模板方法,写一个抽象方法,调用它。具体的实现交给开发人员。

所以Lettuce设计了一个LettuceClientConfigurationBuilderCustomizer的类,他有一个customize方法,并且把上面提到的Builder作为这个方法的参数传递进来。开发人员,如果能去配置LettuceClientConfigurationBuilderCustomizer这样一个类,就能达到上述的目的。

但问题是,如果是开发人员去配置这样一个类,说明LettuceClientConfigurationBuilderCustomizer这个类还没有被实例化。但根据模板模式,流程中必须调用LettuceClientConfigurationBuilderCustomizer这个类的抽象方法,才能达到目的。

这个时候延迟加载,ObjectProvider的作用就体现出来了。他可以规定,他产生的是一个LettuceClientConfigurationBuilderCustomizer的对象,并且指定这个对象产生以后,做什么事情。比如调用customize方法。

如果用户配置了LettuceClientConfigurationBuilderCustomizer对象。那么在创建RedisClient的流程中,ObjectProvider就能拿到该对象,然后按照预先指定的动作执行,比如执行customize方法。

如果用户没配置,那么拿不到Bean对象,就什么都不做。

所以这个场景,我认为是延迟查找的一个典型实现

// 根本在于函数式接口的使用   就是下面的第四行
private void customize(LettuceClientConfiguration.LettuceClientConfigurationBuilder builder) {
    
    
	this.builderCustomizers.orderedStream()
		.forEach((customizer) -> customizer.customize(builder));
}

熟悉ObjectFactory的子接口-ObjectProvider接口

public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
    
    

	// 返回对象一个实例,args为创建相应实例时使用的参数
	T getObject(Object... args) throws BeansException;

	// 返回bean实例,如果不可用则为空
	@Nullable
	T getIfAvailable() throws BeansException;

	// 返回bean实例,如果不可用则使用默认的Supplier
	default T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {
    
    
		T dependency = getIfAvailable();
		return (dependency != null ? dependency : defaultSupplier.get());
	}

	// 如果可用,调用消费者
	default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
    
    
		T dependency = getIfAvailable();
		if (dependency != null) {
    
    
			dependencyConsumer.accept(dependency);
		}
	}

	// 如果不可用或不唯一,则为空
	@Nullable
	T getIfUnique() throws BeansException;

	// 如果不可用或不唯一,则使用Supplier
	default T getIfUnique(Supplier<T> defaultSupplier) throws BeansException {
    
    
		T dependency = getIfUnique();
		return (dependency != null ? dependency : defaultSupplier.get());
	}

	// 如果可用唯一,调用消费者Consumer
	default void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {
    
    
		T dependency = getIfUnique();
		if (dependency != null) {
    
    
			dependencyConsumer.accept(dependency);
		}
	}

	// 可遍历,支持stream
	@Override
	default Iterator<T> iterator() {
    
    
		return stream().iterator();
	}

	
	default Stream<T> stream() {
    
    
		throw new UnsupportedOperationException("Multi element access not supported");
	}

	// 获取排序后的数据流
	default Stream<T> orderedStream() {
    
    
		throw new UnsupportedOperationException("Ordered element access not supported");
	}

}

延迟加载ObjectProvider使用示例

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

/**
 * 通过 {@link ObjectProvider} 进行依赖查找
 */
public class ObjectProviderDemo {
    
     // 这里@Configuration 是非必须注解

    public static void main(String[] args) {
    
    
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 将当前类 ObjectProviderDemo 作为配置类(Configuration Class)
        applicationContext.register(ObjectProviderDemo.class);
        // 启动应用上下文
        applicationContext.refresh();
        // 依赖查找集合对象
        lookupByObjectProvider(applicationContext);
        lookupIfAvailable(applicationContext);
        lookupByStreamOps(applicationContext);

        // 关闭应用上下文
        applicationContext.close();

    }

    private static void lookupByStreamOps(AnnotationConfigApplicationContext applicationContext) {
    
    
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
//        Iterable<String> stringIterable = objectProvider;
//        for (String string : stringIterable) {
    
    
//            System.out.println(string);
//        }
        // Stream -> Method reference
        objectProvider.stream().forEach(System.out::println);
    }

    private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {
    
    
        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        User user = userObjectProvider.getIfAvailable(User::createUser); // 如果没有,就创建对象
        System.out.println("当前 User 对象:" + user);
    }

    @Bean
    @Primary
    public String helloWorld() {
    
     // 方法名就是 Bean 名称 = "helloWorld"
        return "Hello,World";
    }

    @Bean
    public String message() {
    
    
        return "Message";
    }

    private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
    
    
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        System.out.println(objectProvider.getObject());
    }
}

5、依赖查找的异常安全性

依赖查找类型 代表实现— 是否安全
单一类型查找 BeanFactory#getBean
ObjectFactory#getObject
ObjectProvider#getIfAvailable
集合类型查找 ListableBeanFactory#getBeansOfType
ObjectProvider#stream

注意:层次性依赖查找的安全性取决于其扩展的单一或集合类型的 BeanFactory 接口

安全依赖查找代码实例


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 类型安全 依赖查找示例
 */
public class TypeSafetyDependencyLookupDemo {
    
    

    public static void main(String[] args) {
    
    
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 将当前类 TypeSafetyDependencyLookupDemo 作为配置类(Configuration Class)
        applicationContext.register(TypeSafetyDependencyLookupDemo.class); // 这里面是没有User的
        // 启动应用上下文
        applicationContext.refresh();

        // 演示 BeanFactory#getBean 方法的安全性
        displayBeanFactoryGetBean(applicationContext);
        // 演示 ObjectFactory#getObject 方法的安全性
        displayObjectFactoryGetObject(applicationContext);
        // 演示 ObjectProvider#getIfAvaiable 方法的安全性
        displayObjectProviderIfAvailable(applicationContext);

        // 演示 ListableBeanFactory#getBeansOfType 方法的安全性
        displayListableBeanFactoryGetBeansOfType(applicationContext);
        // 演示 ObjectProvider Stream 操作的安全性
        displayObjectProviderStreamOps(applicationContext);

        // 关闭应用上下文
        applicationContext.close();
    }

    private static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext applicationContext) {
    
    
        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        /**
         * userObjectProvider.forEach是安全的
         */
        printBeansException("displayObjectProviderStreamOps", () -> userObjectProvider.forEach(System.out::println));
    }

    private static void displayListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory) {
    
    
        /**
         * beanFactory.getBeansOfType(User.class) 是安全的
         * 找不到bean不会抛异常,会返回空(并不是null)
         */
        printBeansException("displayListableBeanFactoryGetBeansOfType", () -> beanFactory.getBeansOfType(User.class));
    }

    private static void displayObjectProviderIfAvailable(AnnotationConfigApplicationContext applicationContext) {
    
    
        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        /**
         * objectProvider.getIfAvailable() 是安全的
         * 找不到bean会返回null
         */
        printBeansException("displayObjectProviderIfAvailable", () -> userObjectProvider.getIfAvailable());
    }

    private static void displayObjectFactoryGetObject(AnnotationConfigApplicationContext applicationContext) {
    
    
        // ObjectProvider 等价于 ObjectFactory
        ObjectFactory<User> userObjectFactory = applicationContext.getBeanProvider(User.class);
        /**
         * ObjectFactory.getObject()不安全!
         * 没有该Bean会抛异常
         */
        printBeansException("displayObjectFactoryGetObject", () -> userObjectFactory.getObject());
    }

    public static void displayBeanFactoryGetBean(BeanFactory beanFactory) {
    
    
        /**
         * beanFactory.getBean(User.class) 不安全!
         * beanFactory.getBean(class); 有三种情况会抛异常
         * NoSuchBeanDefinitionException -如果没有找到给定类型的bean
         * NoUniqueBeanDefinitionException——如果找到了多个给定类型的bean
         * BeansException -如果无法创建bean
         */
        printBeansException("displayBeanFactoryGetBean", () -> beanFactory.getBean(User.class));
    }

    private static void printBeansException(String source, Runnable runnable) {
    
    
        System.err.println("==========================================");
        System.err.println("Source from :" + source);
        try {
    
    
            runnable.run();
        } catch (BeansException exception) {
    
    
            exception.printStackTrace();
        }
    }
}

由依赖查找的异常安全性做出的总结

日常开发中能用异常安全的方式获取Bean就用安全的方式获取Bean,这里推荐使用ObjectProvider的方式获取Bean,既可以单一类型查找,又可以集合类型查找,使用方便还安全。

6、Spring内建可查找的依赖

AbstractApplicationContext 内建可查找的依赖

Bean 名称 Bean 实例 使用场景
environment Environment 对象 外部化配置(-D启动参数)以及 Profiles
systemProperties java.util.Properties 对象 Java 系统属性
systemEnvironment java.util.Map 对象 操作系统环境变量(当前用户)
messageSource MessageSource 对象 国际化文案
lifecycleProcessor LifecycleProcessor 对象 Lifecycle Bean 处理器
applicationEventMulticaster ApplicationEventMulticaster 对象 Spring 事件广播器

注解驱动 Spring 应用上下文内建可查找的依赖

Bean 名称 Bean 实例 使用场景
org.springframework.context.annotation.internalConfigurationAnnotationProcessor ConfigurationClassPostProcessor 对象 处理 Spring 配置类
org.springframework.context.annotation.internalAutowiredAnnotationProcessor AutowiredAnnotationBeanPostProcessor 对象 处理 @Autowired 以及 @Value注解
org.springframework.context.annotation.internalCommonAnnotationProcessor CommonAnnotationBeanPostProcessor 对象 (条件激活)处理 JSR-250 注解,如 @PostConstruct 等
org.springframework.context.event.internalEventListenerProcessor EventListenerMethodProcessor对象 处理标注 @EventListener 的Spring 事件监听方法
org.springframework.context.event.internalEventListenerFactory DefaultEventListenerFactory 对象 @EventListener 事件监听方法适配为 ApplicationListener
org.springframework.context.annotation.internalPersistenceAnnotationProcessor PersistenceAnnotationBeanPostProcessor 对象 (条件激活)处理 JPA 注解场景

1、ConfigurationClassPostProcessor
标注了@Configuration 的类,底层是由ConfigurationClass处理的。
而ConfigurationClassPostProcessor 实现了BeanDefinitionRegistryPostProcessor,用于处理BeanFactory的生命周期回调。

2、AutowiredAnnotationBeanPostProcessor

从其构造器也可以看出,它是处理@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.
	}
}

7、依赖查找中的经典异常

BeansException 子类型

异常类型 触发条件(举例) 场景举例
NoSuchBeanDefinitionException 当查找 Bean 不存在于 IoC 容器时 BeanFactory#getBean、 ObjectFactory#getObject
NoUniqueBeanDefinitionException 类型依赖查找时,IoC 容器存在多个 Bean 实例 BeanFactory#getBean(Class)
BeanInstantiationException 当 Bean 所对应的类型非具体类时 BeanFactory#getBean
BeanCreationException 当 Bean 初始化过程中 Bean 初始化方法执行异常时
BeanDefinitionStoreException 当 BeanDefinition 配置元信息非法时 XML 配置资源无法打开时

附1:各个BeanFactory的继承关系

在这里插入图片描述

附2:ApplicationContext继承关系

在这里插入图片描述

二、依赖注入

依赖注入类型:

依赖注入类型 配置元数据举例
Setter 方法 <proeprty name=”user” ref=”userBean” />
构造器 <constructor-arg name=“user” ref=“userBean” />
字段 @Autowired User user;
方法 @Autowired public void user(User user) { … }
接口回调 class MyBean implements BeanFactoryAware { … }

1、自动绑定(Autowiring-区别于@Autowired)

其实自动绑定的方式更多的是使用xml的方式,实际自动绑定有很多限制和不足,日常开发过程中较少使用。

模式 说明
no 默认值,未激活 Autowiring,需要手动指定依赖注入对象
byName 根据被注入属性的名称作为 Bean 名称进行依赖查找,并将对象设置到该属性
byType 根据被注入属性的类型作为依赖类型进行查找,并将对象设置到该属性
constructor 特殊 byType 类型,用于构造器参数
<!--使用ref的方式,可以将addressBean命名的bean绑定到address字段-->
<!--使用parent的方式,指定父类-->
<bean id="superUser" class="com.demo.domain.SuperUser" parent="user">
    <property name="address" ref="addressBean"/>
</bean>

<!--autowire自动绑定有多种模式,上面已经介绍过 -->
<bean id="user" class="com.demo.domain.SuperUser" autowire="byName">
</bean>

每种自动绑定的模式都或多或少有一些坑:

  • no:需要自己手动指定注入对象,value或者ref。
  • byName:属性名与被注入的bean名必须相同,如果有修改需要同步修改。
  • byType:如果有多个类型的bean,需要指定@Primary。不能绑定如String类型这种原生类型。

Autowire是一个枚举,指定的自动绑定的模式:

// 我们可以看到,枚举类型并没有构造器绑定,其实构造器绑定就是一种byType绑定
// 具体详情可以查看AutowireCapableBeanFactory
public enum Autowire {
    
    

	/**
	 * Constant that indicates no autowiring at all.
	 */
	NO(AutowireCapableBeanFactory.AUTOWIRE_NO),

	/**
	 * Constant that indicates autowiring bean properties by name.
	 */
	BY_NAME(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME),

	/**
	 * Constant that indicates autowiring bean properties by type.
	 */
	BY_TYPE(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);

	public boolean isAutowire() {
    
    
		return (this == BY_NAME || this == BY_TYPE);
	}

}

2、Setter 方法注入

自动Setter注入

自动Setter注入有byName和byType的方式,具体参考上面介绍的自动绑定。

手动Setter注入

1、XML资源配置元信息

<!-- 使用name+value的方式,可以实现手动Setter注入 -->
<bean class="com.demo.User">
    <property name="name" value="张三" />
</bean>

2、Java 注解配置元信息

// User在容器中已经注册过了,只需要作为方法参数传过来,就会自动获取到
@Bean
public UserHolder userHolder(User user) {
    
    
    UserHolder userHolder = new UserHolder();
    userHolder.setUser(user);
    return userHolder;
}

3、API 配置元信息

// 生成 UserHolder 的 BeanDefinition
BeanDefinition userHolderBeanDefinition = createUserHolderBeanDefinition();
// 注册 UserHolder 的 BeanDefinition
applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);

// 生成UserHolder 的 BeanDefinition
private static BeanDefinition createUserHolderBeanDefinition() {
    
    
    BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
    definitionBuilder.addPropertyReference("user", "superUser"); // 设置属性关联,将superUser命名的bean,赋值到user属性
    return definitionBuilder.getBeanDefinition();
}

3、构造器注入(官方推荐)

自动构造器注入

详情请看文章上面,自动绑定。

<bean class="com.cxf.test.UserHolder"
      autowire="constructor">
    <!--        <property name="user" ref="superUser" /> 替换成 autowiring 模式 -->
</bean>

手动构造器注入

1、xml方式

<!--自定义构造器参数,ref代表bean的名称 -->
<bean class="com.cxf.test.UserHolder">
    <constructor-arg name="user" ref="superUser" />
</bean>
public class UserHolder {
    
    

    private User user;

    public UserHolder(User user) {
    
    
        this.user = user;
    }

2、注解方式

@Bean
public UserHolder userHolder(User user) {
    
    
    return new UserHolder(user);
}

3、API方式

private static BeanDefinition createUserHolderBeanDefinition() {
    
    
    BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
    definitionBuilder.addConstructorArgReference("superUser"); // 自动找到名称为superUser的bean,注入到构造器
    return definitionBuilder.getBeanDefinition();
}

4、字段注入

字段注入一般使用Java 注解配置元信息:

  • @Autowired
  • @Resource
  • @Inject(可选)
/**
使用@Autowired 注入,默认根据类型注入,然后根据name注入
注意!@Autowired会忽略static类型的字段,具体源码后续再讲
*/
@Autowired
private UserHolder userHolder;

/**
使用@Resource 注入,默认根据类型注入,然后根据name注入
*/
@Resource
private UserHolder userHolder2;

/**
使用@Inject 注入,需要依赖JSR-330的jar包,这里略
*/

5、方法注入

方法注入一般使用Java 注解配置元信息:

  • @Autowired
  • @Resource
  • @Inject(可选)
  • @Bean

方法注入会自动匹配bean为方法的参数,将其注入到方法的参数中。

方法注入不走 factorybean, Setter 注入是通过 Java Beans 来实现的,而方法注入则是直接通过 Java 反射来做的。当然底层都是 Java 反射~

private UserHolder userHolder;

private UserHolder userHolder2;

@Autowired
public void init1(UserHolder userHolder) {
    
    
    this.userHolder = userHolder;
}

@Resource
public void init2(UserHolder userHolder2) {
    
    
    this.userHolder2 = userHolder2;
}

@Bean
public UserHolder userHolder(User user) {
    
    
    return new UserHolder(user);
}

6、接口回调注入

Aware 系列接口回调。

內建接口 说明
BeanFactoryAware 获取当前 IoC 容器 - BeanFactory
ApplicationContextAware 获取 Spring 应用上下文 - ApplicationContext 对象
EnvironmentAware 获取 Environment 对象
ResourceLoaderAware 获取资源加载器 对象 - ResourceLoader
BeanClassLoaderAware 获取加载当前 Bean Class 的 ClassLoader
BeanNameAware 获取当前 Bean 的名称
MessageSourceAware 获取 MessageSource 对象,用于 Spring 国际化
ApplicationEventPublisherAware 获取 ApplicationEventPublishAware 对象,用于 Spring 事件
EmbeddedValueResolverAware 获取 StringValueResolver 对象,用于占位符处理
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 基于 {@link Aware} 接口回调的依赖注入示例
 */
public class AwareInterfaceDependencyInjectionDemo implements BeanFactoryAware, ApplicationContextAware {
    
    

    private static BeanFactory beanFactory;

    private static ApplicationContext applicationContext;


    public static void main(String[] args) {
    
    

        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类) -> Spring Bean
        context.register(AwareInterfaceDependencyInjectionDemo.class);

        // 启动 Spring 应用上下文
        context.refresh();

        System.out.println(beanFactory == context.getBeanFactory());
        System.out.println(applicationContext == context);

        // 显示地关闭 Spring 应用上下文
        context.close();
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    
    
        AwareInterfaceDependencyInjectionDemo.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
    
        AwareInterfaceDependencyInjectionDemo.applicationContext = applicationContext;
    }
}

7、各种依赖注入比较

注入方式 优点 缺点
构造器注入 通用性强,官方推荐 无法解决循环依赖问题;参数过多的话可读性差
Setter 方法注入 解决循环依赖问题 不能将对象设置为final
字段注入 使用便捷 不能将字段设为final、static;无法解决循环依赖问题
方法注入 一般与@Bean配合使用,@Autowire、@Resource用的较少

8、基础类型的注入

  • 原生类型(Primitive):boolean、byte、char、short、int、float、long、double
  • 标量类型(Scalar):Number、Character、Boolean、Enum、Locale、Charset、Currency、Properties、UUID
  • 常规类型(General):Object、String、TimeZone、Calendar、Optional 等
  • Spring 类型:Resource、InputSource、Formatter 等

使用xml配置的方式,一些基础类型的配置涉及自动类型转换:


public class User {
    
    
    private Long id;
    private String name;
    private City city; // 枚举
    private Resource configFileLocation; // 资源

public enum City {
    
    
    BEIJING,
    HANGZHOU,
    SHANGHAI
}

<bean id="user" class="com.demo.domain.User">
    <property name="id" value="1"/>
    <property name="name" value="张三"/>
    <property name="city" value="HANGZHOU"/>
    <property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/>
</bean>

9、集合类型注入

  • 数组类型(Array):原生类型、标量类型、常规类型、Spring 类型
  • 集合类型(Collection)
    • Collection:List、Set(SortedSet、NavigableSet、EnumSet)
    • Map:Properties
public class User {
    
    
    private City[] workCities; // 数组
    private List<City> lifeCities; // list

public enum City {
    
    
    BEIJING,
    HANGZHOU,
    SHANGHAI
}

<bean id="user" class="com.demo.domain.User">
    <property name="workCities" value="BEIJING,HANGZHOU"/> <!-- list也可以用这种方式写 -->
    <property name="lifeCities">
        <list>
            <value>BEIJING</value>
            <value>SHANGHAI</value>
        </list>
    </property>
</bean>

10、限定注入

使用注解 @Qualifier 通过Bean 名称限定

有多个同类型的Bean时,使用@Primary指定默认的Bean之后,再使用@Autowired会自动注入使用@Primary指定的Bean,否则会报错。

使用@Qualifier(“user”),可以注入指定名称的bean。

@Autowired
private User user; 

@Autowired
@Qualifier("user") // 指定 Bean 名称或 ID
private User namedUser;

@Bean
public User user() {
    
    
    return createUser(5L);
}

@Bean
@Primary // 指定默认
public User users() {
    
    
    return createUser(6L);
}

使用注解 @Qualifier 通过分组限定

当使用@Bean定义一个bean时,同时使用@Qualifier标注,此bean就会被分组。
使用@Autowired注入时,同时使用@Qualifier标注,会取出分组过的bean。

@Autowired // 注入所有User类型的Bean
private Collection<User> allUsers; 

@Autowired
@Qualifier // 取出所有使用@Qualifier标注的bean
private Collection<User> qualifiedUsers; 

@Bean
@Qualifier // 进行逻辑分组
public User user1() {
    
    
    return createUser(7L);
}

@Bean
@Qualifier // 进行逻辑分组
public  User user2() {
    
    
    return createUser(8L);

}

基于注解 @Qualifier 扩展限定

(自定义注解 - 实际应用如 Spring Cloud @LoadBalanced)

我们可以使用@Qualifier扩展分组,扩展后的用法与@Qualifier相同。

@Target({
    
    ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier
public @interface UserGroup {
    
    
}

@Autowired
@UserGroup
private Collection<User> groupedUsers;


@Bean
@UserGroup
public  User user3() {
    
    
    return createUser(9L);
}

@Bean
@UserGroup
public  User user4() {
    
    
    return createUser(10L);
}

案例

@Target({
    
    ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier
public @interface UserGroup {
    
    
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.util.Collection;

@Configuration
public class QualifierAnnotationDependencyInjectionDemo {
    
    

    @Autowired // 注入使用 @Primary标注的bean
    private User user;

    @Autowired
    @Qualifier("user") // 指定 Bean 名称或 ID
    private User namedUser;
    
    @Autowired // 注入所有User类型的bean
    private Collection<User> allUsers; 

    @Autowired
    @Qualifier // 注入使用@Qualifier 分组的bean
    private Collection<User> qualifiedUsers;

    @Autowired
    @UserGroup // 注入使用@UserGroup、@Qualifier分组的bean(因为@UserGroup用@Qualifier标注了)
    private Collection<User> groupedUsers;


    @Bean
    public User user() {
    
    
        return createUser(5L);
    }

    @Bean
    @Primary // 指定默认
    public User users() {
    
    
        return createUser(6L);
    }

    @Bean
    @Qualifier // 进行逻辑分组
    public User user1() {
    
    
        return createUser(7L);
    }

    @Bean
    @Qualifier // 进行逻辑分组
    public User user2() {
    
    
        return createUser(8L);

    }

    @Bean
    @UserGroup
    public User user3() {
    
    
        return createUser(9L);
    }

    @Bean
    @UserGroup
    public User user4() {
    
    
        return createUser(10L);
    }

    private static User createUser(Long id) {
    
    
        User user = new User();
        user.setId(id);
        return user;
    }

    public static void main(String[] args) {
    
    

        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类) -> Spring Bean
        applicationContext.register(QualifierAnnotationDependencyInjectionDemo.class);

        // 启动 Spring 应用上下文
        applicationContext.refresh();

        // 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
        QualifierAnnotationDependencyInjectionDemo demo = applicationContext.getBean(QualifierAnnotationDependencyInjectionDemo.class);

        // 期待输出 superUser Bean
        System.out.println("demo.user = " + demo.user);
        // 期待输出 user Bean
        System.out.println("demo.namedUser = " + demo.namedUser);
        // 期待输出 superUser user user1 user2
        System.out.println("demo.allUsers = " + demo.allUsers);
        // 期待输出 user1 user2
        System.out.println("demo.qualifiedUsers = " + demo.qualifiedUsers);
        // 期待输出 user3 user4
        System.out.println("demo.groupedUsers = " + demo.groupedUsers);


        // 显示地关闭 Spring 应用上下文
        applicationContext.close();
    }
}

// 输出内容
demo.user = User{
    
    id=6}
demo.namedUser = User{
    
    id=5}
demo.allUsers = [User{
    
    id=5}, User{
    
    id=6}, User{
    
    id=7}, User{
    
    id=8}, User{
    
    id=9}, User{
    
    id=10}]
demo.qualifiedUsers = [User{
    
    id=7}, User{
    
    id=8}, User{
    
    id=9}, User{
    
    id=10}]
demo.groupedUsers = [User{
    
    id=9}, User{
    
    id=10}]

11、延迟依赖注入

延迟依赖注入请参考【延迟依赖查找】。

通常的 @Autowired 会及时依赖相关的 Spring Bean,不过此时 Bean 的状态并未完全准备好,所以 ObjectProvider 可以在需要时获取 Spring Bean,更好的状态准备,达到延迟的获取效果。(更多请查阅【Spring如何解决循环依赖的】)

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Collection;
import java.util.Set;

/**
 * {@link ObjectProvider} 实现延迟依赖注入
 */
@Configuration
public class LazyAnnotationDependencyInjectionDemo {
    
    

    @Autowired
    @Qualifier("user")
    private User user; // 实时注入

    @Autowired
    private ObjectProvider<User> userObjectProvider; // 使用 API ObjectFactory 延迟注入

    @Autowired
    private ObjectFactory<Set<User>> usersObjectFactory; // 使用 API ObjectProvider 延迟注入(推荐)

    @Bean
    public User user() {
    
    
        return createUser(10L);
    }

    private static User createUser(Long id) {
    
    
        User user = new User();
        user.setId(id);
        return user;
    }

    public static void main(String[] args) {
    
    

        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类) -> Spring Bean
        applicationContext.register(LazyAnnotationDependencyInjectionDemo.class);

        // 启动 Spring 应用上下文
        applicationContext.refresh();

        // 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
        LazyAnnotationDependencyInjectionDemo demo = applicationContext.getBean(LazyAnnotationDependencyInjectionDemo.class);

        // 期待输出 superUser Bean
        System.out.println("demo.user = " + demo.user);
        // 期待输出 superUser Bean
        System.out.println("demo.userObjectProvider = " + demo.userObjectProvider.getObject()); // 继承 ObjectFactory
        // 期待输出 superUser user Beans
        System.out.println("demo.usersObjectFactory = " + demo.usersObjectFactory.getObject());

        demo.userObjectProvider.forEach(System.out::println);

        // 显示地关闭 Spring 应用上下文
        applicationContext.close();
    }
}

12、Optional类型注入

java8开始支持Optional类型,直接定义Optional的泛型,就会根据定义的泛型进行注入。

@Autowired
private Optional<User> userOptional;

13、依赖注入处理的过程源码分析

入口 - DefaultListableBeanFactory#resolveDependency

// org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
    

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	if (Optional.class == descriptor.getDependencyType()) {
    
     // java8开始支持Optional
		return createOptionalDependency(descriptor, requestingBeanName);
	}
	else if (ObjectFactory.class == descriptor.getDependencyType() ||
			ObjectProvider.class == descriptor.getDependencyType()) {
    
     // 支持ObjectProvider
		return new DependencyObjectProvider(descriptor, requestingBeanName);
	}
	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
    
     // Java 中jsr330注入方式
		return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
    
     // 默认操作
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( // 是否懒加载
				descriptor, requestingBeanName);
		if (result == null) {
    
    
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}
// org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
    

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
    
    
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
    
    
			return shortcut;
		}

		Class<?> type = descriptor.getDependencyType();
		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);
				value = evaluateBeanDefinitionString(strVal, bd);
			}
			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()));
			}
		}

		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
		if (multipleBeans != null) {
    
    
			return multipleBeans;
		}

		// 会返回多个bean
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {
    
    
			if (isRequired(descriptor)) {
    
    
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		if (matchingBeans.size() > 1) {
    
     // 多个bean
			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();
		}

		if (autowiredBeanNames != null) {
    
    
			autowiredBeanNames.add(autowiredBeanName);
		}
		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);
	}
}
// org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates
protected Map<String, Object> findAutowireCandidates(
		@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    
    

	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
	Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
	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) {
    
    
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
    
    
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}
	if (result.isEmpty()) {
    
    
		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);
			}
		}
		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;
}
// 获取bean集合
// org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
    
    

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

	if (descriptor instanceof StreamDependencyDescriptor) {
    
    
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (autowiredBeanNames != null) {
    
    
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		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;
		}
		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);
		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;
	}
}

14、详解@Autowired 注入

重要类:AutowiredAnnotationBeanPostProcessor。

@Autowired注入过程(所有方法都在AutowiredAnnotationBeanPostProcessor#类里)
(1)调用postProcessProperties()方法(spring 5.1之后才是这个方法名,5.1之前是postProcessPropertyValues)
该步骤信息点:
a. postProcessProperties方法会比bean的setXX()方法先调用
b.findAutowiringMetadata()方法会找出一个bean加了@Autowired注解的字段(包括父类的),并且该方法做了缓存
c.xml配置的bean与bean之间是可以有继承关系的,有另一个周期(不是autowired的流程)是把配置super bean的属性合并到当前bean,之后会调用后置方法postProcessMergedBeanDefinition,该方法也会调用一次findAutowiringMetadata
d.经测试,postProcessMergedBeanDefinition会比postProcessProperties先执行,因此调用postProcessProperties时都是直接拿缓存
(2)—>inject方法(获得对应的bean,然后通过反射注入到类的字段上)
(3)inject方法会调用resolveDependency方法,这方法会根据@Autowired字段信息来匹配出符合条件的bean

// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    
    
	Field field = (Field) this.member;
	Object value;
	if (this.cached) {
    
    
		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);
	}
}

// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue
@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;
				registerDependentBeans(beanName, autowiredBeanNames);
				if (autowiredBeanNames.size() == 1) {
    
    
					String autowiredBeanName = autowiredBeanNames.iterator().next();
					if (beanFactory.containsBean(autowiredBeanName) &&
							beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
    
    
						cachedFieldValue = new ShortcutDependencyDescriptor(
								desc, autowiredBeanName, field.getType());
					}
				}
			}
			this.cachedFieldValue = cachedFieldValue;
			this.cached = true;
		}
	}
	return value;
}

15、JSR-330 @Inject 注入

要用@Inject,首先要引入jar包:

<!-- JSR-330 API -->
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

通过添加JSR-330的依赖来让AutowiredAnnotationBeanPostProcessor支持@Inject的annotationType。

// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#AutowiredAnnotationBeanPostProcessor
// 可以处理@Autowired、@Value、以及判断是否有@Inject 选择是否支持
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.
	}
}

// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation
// 一个字段同时标注三个注解时,注解处理有序,@Autowired > @Value > @Inject
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    
    
	MergedAnnotations annotations = MergedAnnotations.from(ao);
	for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
    
    
		MergedAnnotation<?> annotation = annotations.get(type);
		if (annotation.isPresent()) {
    
    
			return annotation;
		}
	}
	return null;
}

@Inject 的使用和@Autowired 并没有区别:

@Inject
private User injectedUser;

16、Java通用注解注入原理

主处理类:CommonAnnotationBeanPostProcessor(与AutowiredAnnotationBeanPostProcessor非常类似)

注入注解:

  • javax.xml.ws.WebServiceRef
  • javax.ejb.EJB
  • javax.annotation.Resource

生命周期注解:

  • javax.annotation.PostConstruct
  • javax.annotation.PreDestroy
// 支持以上注解:WebServiceRef、EJB、Resource、PostConstruct、PreDestroy
static {
    
    
	resourceAnnotationTypes.add(Resource.class);

	webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
	if (webServiceRefClass != null) {
    
    
		resourceAnnotationTypes.add(webServiceRefClass);
	}

	ejbClass = loadAnnotationType("javax.ejb.EJB");
	if (ejbClass != null) {
    
    
		resourceAnnotationTypes.add(ejbClass);
	}
}

public CommonAnnotationBeanPostProcessor() {
    
    
	setOrder(Ordered.LOWEST_PRECEDENCE - 3);// 注意!优先级顺序
	setInitAnnotationType(PostConstruct.class);
	setDestroyAnnotationType(PreDestroy.class);
	ignoreResourceType("javax.xml.ws.WebServiceContext");

	// java.naming module present on JDK 9+?
	if (jndiPresent) {
    
    
		this.jndiFactory = new SimpleJndiBeanFactory();
	}
}
// 生命周期回调:org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#buildLifecycleMetadata
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
    
    
	if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
    
    
		return this.emptyLifecycleMetadata;
	}

	List<LifecycleElement> initMethods = new ArrayList<>(); // 只允许绑定方法,LifecycleElement中有invoke方法
	List<LifecycleElement> destroyMethods = new ArrayList<>(); // 只允许绑定方法,LifecycleElement中有invoke方法
	Class<?> targetClass = clazz;

	do {
    
    
		final List<LifecycleElement> currInitMethods = new ArrayList<>();
		final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

		// 构建原信息
		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    
    
			if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
    
    
				LifecycleElement element = new LifecycleElement(method);
				currInitMethods.add(element);
				if (logger.isTraceEnabled()) {
    
    
					logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
				}
			}
			if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
    
    
				currDestroyMethods.add(new LifecycleElement(method));
				if (logger.isTraceEnabled()) {
    
    
					logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
				}
			}
		});

		initMethods.addAll(0, currInitMethods);
		destroyMethods.addAll(currDestroyMethods);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);

	return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
			new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
// org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.LifecycleElement
private static class LifecycleElement {
    
    

	private final Method method;

	private final String identifier;

	public LifecycleElement(Method method) {
    
    
		if (method.getParameterCount() != 0) {
    
    
			throw new IllegalStateException("Lifecycle method annotation requires a no-arg method: " + method);
		}
		this.method = method;
		this.identifier = (Modifier.isPrivate(method.getModifiers()) ?
				ClassUtils.getQualifiedMethodName(method) : method.getName());
	}

	public Method getMethod() {
    
    
		return this.method;
	}

	public String getIdentifier() {
    
    
		return this.identifier;
	}

	// 方法回调执行
	public void invoke(Object target) throws Throwable {
    
    
		ReflectionUtils.makeAccessible(this.method);
		this.method.invoke(target, (Object[]) null);
	}

	@Override
	public boolean equals(@Nullable Object other) {
    
    
		if (this == other) {
    
    
			return true;
		}
		if (!(other instanceof LifecycleElement)) {
    
    
			return false;
		}
		LifecycleElement otherElement = (LifecycleElement) other;
		return (this.identifier.equals(otherElement.identifier));
	}

	@Override
	public int hashCode() {
    
    
		return this.identifier.hashCode();
	}
}

17、自定义依赖注入注解

基于@Autowired元注解创建自定义注解

// 可以自行扩展
@Target({
    
    ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Autowired
public @interface MyAutowired {
    
    

    /**
     * Declares whether the annotated dependency is required.
     * <p>Defaults to {@code true}.
     */
    boolean required() default true;
}
// 与@Autowired用法一致,可以自行扩展
@MyAutowired
private Optional<User> userOptional;

基于 AutowiredAnnotationBeanPostProcessor 实现

1、使用方式一:

/**
 * 自定义依赖注入注解
 */
@Target({
    
    ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD}) // 指定标注的位置
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InjectedUser {
    
    
}

// Bean非常想要提前初始化 或者提前注册的话,可以将方法定义为static的
@Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
    
    
    AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
    // @Autowired + @Inject +  新注解 @InjectedUser
    Set<Class<? extends Annotation>> autowiredAnnotationTypes =
            new LinkedHashSet<>(Arrays.asList(Autowired.class, Inject.class, InjectedUser.class));
    beanPostProcessor.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
    return beanPostProcessor;
}

// 使用新注解
@InjectedUser
private User myInjectedUser;

这种方式是完全将之前的AutowiredAnnotationBeanPostProcessor 替换了,但是@Inject有可能并没有引包,所以这里有一些小缺陷。

2、使用方式二:

先注册系统的AutowiredAnnotationBeanPostProcessor,再注册自定义的AutowiredAnnotationBeanPostProcessor,可以让两个同时存在。

@Bean
// 正常的@Autowired注解优先级为Ordered.LOWEST_PRECEDENCE - 2,这里比系统的AutowiredAnnotationBeanPostProcessor优先级低,会同时存在
@Order(Ordered.LOWEST_PRECEDENCE - 3)
public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
    
    
    AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
    beanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);
    return beanPostProcessor;
}

3、原理
在org.springframework.context.annotation.AnnotationConfigUtils 定义了一个bean:

public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
		"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";

// Bean不存在才自动注入,如果存在会优先使用用户自定义的
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));
}

自定义实现(略)

生命周期处理

  • InstantiationAwareBeanPostProcessor
  • MergedBeanDefinitionPostProcessor

元数据

  • InjectedElement
  • InjectionMetadata

19、附:关于加static的bean会提前注册问题

因为当 @Bean 方法定义是非 static 的话,那么它的初始化依赖于所属类 Bean 的初始化,而处理Demo属性的注入@Autowired属于Demo这个Bean初始化的一个环节,所以当 @Autowired 字段发生时,BeanPostProcessor后置处理器并没有创建好,所以@Autowired注解会失效。
采用static,将创建BeanPostProcessor后置处理器提前到了初始化Demo这个Bean之前,所以能够处理@Autowired注解。

猜你喜欢

转载自blog.csdn.net/A_art_xiang/article/details/128126908