在新spring框架(4.x系列)源码中经常可以看到ObjectProvider
//源自org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration
@Configuration
@AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
public class WebClientAutoConfiguration {
@Configuration
@ConditionalOnClass(RestTemplate.class)
public static class RestTemplateConfiguration {
private final ObjectProvider messageConverters;
private final ObjectProvider> restTemplateCustomizers;
public RestTemplateConfiguration(
ObjectProvider messageConverters,
ObjectProvider> 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 extends ObjectFactory {
....
@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
因此,从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 repositoryProvider) {
this.repository = repositoryProvider.getIfUnique();
}
}
它的核心源码在DefaultListableBeanFactory中,了解BeanFactory的这个其实也不陌生。