spring ObjectProvider 源码分析

在新spring框架(4.x系列)源码中经常可以看到ObjectProvider<T>的语法,而在度娘查找资料,你发现几乎找不到能讲清楚它来龙去脉的文章,下面将本着寻根溯源的态度去研究它。

//源自org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration
@Configuration
@AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
public class WebClientAutoConfiguration {

	@Configuration
	@ConditionalOnClass(RestTemplate.class)
	public static class RestTemplateConfiguration {

		private final ObjectProvider<HttpMessageConverters> messageConverters;

		private final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers;

		public RestTemplateConfiguration(
				ObjectProvider<HttpMessageConverters> messageConverters,
				ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
			this.messageConverters = messageConverters;
			this.restTemplateCustomizers = restTemplateCustomizers;
		}
.....

首先,学习一个新东西,一定要查阅与它相关的原文资料,再结合源代码去进一步理解它。看它源码:

/**
 * A variant of {@link ObjectFactory} designed specifically for injection points,
 * allowing for programmatic optionality and lenient not-unique handling.
 *
 * @author Juergen Hoeller
 * @since 4.3
 */
public interface ObjectProvider<T> extends ObjectFactory<T> {
....

@since 4.3 :也就是说它是spring 4.3版本才有的新东西

A variant of {@link ObjectFactory} designed specifically for injection points,allowing for programmatic optionality and lenient not-unique handling.

它意思是:属于ObjectFactory的变体,专门为注入点设计,允许编程可选性和宽松的非唯一处理。够抽象吧,别急,继续向下看。

构造函数隐式注入

首先要了解这样的一个事实,4.3系列之前版本,如果你构造函数中要依赖另外一个bean,你必须显示依赖@Autowired ,像这样子

@Service
public class FooService {
    private final FooRepository repository;
    @Autowired
    public FooService(FooRepository repository) {
        this.repository = repository
    }
}

相当常见的用例但是如果你忘记构造函数上的@Autowired注释,容器将抛出一个寻找默认构造函数的异常,除非你在bean定义设置中明确指出autowire模式’constructor’(例如在XML <bean中) >)

因此,从4.3开始,您不再需要在这样的单构造函数场景中指定显式注入注释。对于那些根本不带任何容器注释的类来说,这是特别优雅的,FooService会从beanFactory中查找FooRepository。

同样,您可能已经注意到@Configuration历史上不支持构造函数注入。它们现在从4.3开始,它们显然也允许在单构造函数场景中省略@Autowired

@Service
public class FooService {
    private final FooRepository repository;
    public FooService(FooRepository repository) {
        this.repository = repository
    }
}
@Configuration
public class FooConfiguration {
    private final FooRepository repository;
    public FooConfiguration(FooRepository repository) {
        this.repository = repository
    }
    @Bean
    public FooService fooService() {
        return new FooService(this.repository);
    }
}

但是隐式注入也不是完美的,个人理解不完美是它是强依赖,如果这个依赖不存在,就会发生这样的悲剧:

Parameter 0 of constructor in com.example.demo.FooRepository required a bean of type ‘com.example.demo.OrderServiceV2’ that could not be found.

怎么破?接下来就是今天的主角:ObjectProvider

依赖关系的改进版编程

Spring Framework 4.3引入了ObjectProvider,它是现有ObjectFactory接口的扩展,具有方便的签名,例如getIfAvailable和getIfUnique,只有在它实际存在时才检索bean(可选支持)或者如果可以确定单个候选者(特别是:主要候选者)在多个匹配的bean的情况下)

@Service
public class FooService {
    private final FooRepository repository;
    public FooService(ObjectProvider<FooRepository> repositoryProvider) {
        this.repository = repositoryProvider.getIfUnique();
    }
}

它的核心源码在DefaultListableBeanFactory中

《spring ObjectProvider 源码分析》

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/alex_xfboy/article/details/83342164
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞