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 实例使用场景
environmentEnvironment 对象外部化配置(-D启动参数)以及 Profiles
systemPropertiesjava.util.Properties 对象Java 系统属性
systemEnvironmentjava.util.Map 对象操作系统环境变量(当前用户)
messageSourceMessageSource 对象国际化文案
lifecycleProcessorLifecycleProcessor 对象Lifecycle Bean 处理器
applicationEventMulticasterApplicationEventMulticaster 对象Spring 事件广播器

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

Bean 名称Bean 实例使用场景
org.springframework.context.annotation.internalConfigurationAnnotationProcessorConfigurationClassPostProcessor 对象处理 Spring 配置类
org.springframework.context.annotation.internalAutowiredAnnotationProcessorAutowiredAnnotationBeanPostProcessor 对象处理 @Autowired 以及 @Value注解
org.springframework.context.annotation.internalCommonAnnotationProcessorCommonAnnotationBeanPostProcessor 对象(条件激活)处理 JSR-250 注解,如 @PostConstruct 等
org.springframework.context.event.internalEventListenerProcessorEventListenerMethodProcessor对象处理标注 @EventListener 的Spring 事件监听方法
org.springframework.context.event.internalEventListenerFactoryDefaultEventListenerFactory 对象@EventListener 事件监听方法适配为 ApplicationListener
org.springframework.context.annotation.internalPersistenceAnnotationProcessorPersistenceAnnotationBeanPostProcessor 对象(条件激活)处理 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 // 注入使用@UserGroup、@Qualifier分组的bean(因为@UserGroup用@Qualifier标注了)
    private Collection<User> qualifiedUsers;

    @Autowired
    @UserGroup // 注入使用@UserGroup 分组的bean ,单纯用@Qualifier分组的bean不会注入
    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注解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

秃了也弱了。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值