spring ObjectProvider 源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

在新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<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中

20191102100837\_1.png


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring ObjectProvider 源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏