当前位置 : 主页 > 编程语言 > java >

【Spring源码三千问】@Lazy的替代者ObjectFactory 和 ObjectProvider

来源:互联网 收集:自由互联 发布时间:2022-08-10
@[TOC](别再使用 @Lazy 了,试试 ObjectFactory 和 ObjectProvider) 前言 @Lazy 可以解决某些特殊场景下的循环依赖问题。 在翻阅 @Lazy 的源码注释时,得知 @Lazy 可以通过 ObjectFactory 和 ObjectProvider 来

@[TOC](别再使用 @Lazy 了,试试 ObjectFactory 和 ObjectProvider)

前言

@Lazy 可以解决某些特殊场景下的循环依赖问题。 在翻阅 @Lazy 的源码注释时,得知 @Lazy 可以通过 ObjectFactory 和 ObjectProvider 来进行替代。 下面我们就来看看 ObjectFactory 和 ObjectProvider 的原理和使用吧...

@Lazy 相关的知识: @Lazy为什么可以解决特殊的循环依赖问题 @Lazy延迟加载与延迟注入有什么区别

Spring 版本

Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)

正文

ObjectProvider 作用分析

ObjectProvider 的类图如下: ObjectProvider

ObjectProvider 提供的是通过 ObjectProvider#getObject() 或者 ObjectProvider#getIfAvailable() 获取 Object (即: bean) 的能力。 也就是说,在依赖注入时,注入的是一个 ObjectProvider 对象,想要获取到真正的 bean 时,可以通过调用 ObjectProvider#getObject() 或者 ObjectProvider#getIfAvailable()。 所以,它跟 @Lazy 起到的作用是很相似的。

Spring 对 ObjectProvider 依赖的处理

Spring 在 populateBean 时,会处理依赖属性的注入,最终会调用 DefaultListableBeanFactory#resolveDependency() 来对依赖进行解析。 相关的源码如下: resolveDependency2

可以看到,如果是 ObjectFactory 和 ObjectProvider 类型的依赖,那么会直接 return new DependencyObjectProvider(descriptor, requestingBeanName);,而不会触发依赖 bean 的加载。 等到真正使用 ObjectProvider#getObject() 获取 bean 的时候,才会触发 bean 的加载。

ObjectProvider 的使用场景

ObjectProvider 大量出现在 SpringBoot 的 Configuration 配置类中,做为构造函数的入参来进行使用,即构造注入依赖。

例如 MybatisPlus 中有如下代码:

public MybatisPlusAutoConfiguration(MybatisPlusProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ObjectProvider<TypeHandler[]> typeHandlersProvider, ObjectProvider<LanguageDriver[]> languageDriversProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider, ObjectProvider<List<MybatisPlusPropertiesCustomizer>> mybatisPlusPropertiesCustomizerProvider, ApplicationContext applicationContext) { this.properties = properties; this.interceptors = interceptorsProvider.getIfAvailable(); this.typeHandlers = typeHandlersProvider.getIfAvailable(); this.languageDrivers = languageDriversProvider.getIfAvailable(); this.resourceLoader = resourceLoader; this.databaseIdProvider = databaseIdProvider.getIfAvailable(); this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable(); this.mybatisPlusPropertiesCustomizers = mybatisPlusPropertiesCustomizerProvider.getIfAvailable(); this.applicationContext = applicationContext; }

当然,我们也可以使用 ObjectProvider#getIfAvailable() 来实现类似 required=false 的功能,这是 @Lazy 提供不了能力。 比如:

@Service public class B { @Autowired private ObjectProvider<A> aProvider; public void doBiz(){ A a = this.aProvider.getIfAvailable(); if (a == null) { log.info("a is null"); return; } a.m1(); } }

@Lazy 只能延迟注入,但如果容器中没有这个 bean 的话,在使用时,是会报错的。 所以,ObjectFactory 提供的功能是同 @Lazy 等价的。而 ObjectProvider 可以额外提供 required=false 的能力

小结

ObjectProvider 和 ObjectFactory 都可以提供类似 @Lazy 延迟注入的功能。 另外,ObjectProvider#getIfAvailable() 还可以提供类似 required=false 的功能。

上一篇:如何查看当前电脑上的Maven版本呢?
下一篇:没有了
网友评论