环境:Spring5.3.23
在Spring框架中,依赖注入是一种常见的模式,它能够使代码更加模块化和可维护。然而,在实际开发中,依赖注入也可能会带来一些问题,比如依赖为空或注入方式过于繁琐等。为了解决这些问题,Spring框架提供了ObjectProvider接口,它能够让依赖注入更加灵活和安全。
1. ObjectProvider简介
ObjectProvider是Spring框架中的一个接口,它扩展了ObjectFactory接口,专门为注入点设计。通过使用ObjectProvider,我们可以将对象的创建和注入分开,使得代码更加清晰和可维护。同时,ObjectProvider还支持多态性,可以适应不同的注入场景。
他是ObjectFactory的一种变体,专门为注入点设计,允许编程可选性和宽松的非唯一处理。从5.1开始,该接口扩展了Iterable并提供Stream的支持。因此,它可以用于for循环,提供forEach迭代,并允许集合样式的流访问。核心方法如下:
ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {T getObject(Object... args) throws BeansException;T getIfAvailable() throws BeansException;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);}}T getIfUnique() throws BeansException;default T getIfUnique(Supplier<T> defaultSupplier) throws BeansException {T dependency = getIfUnique();return (dependency != null ? dependency : defaultSupplier.get());}default void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {T dependency = getIfUnique();if (dependency != null) {dependencyConsumer.accept(dependency);}}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");}}
2. 使用ObjectProvider实现依赖注入
案例一:按需注入
MessageService接口和实现类:
public interface MessageService {void sendMessage(String message);}@Servicepublic class SmsMessageServiceImpl implements MessageService {@Overridepublic void sendMessage(String message) {System.out.printf("发送短信:%s%n", message) ;}}
使用ObjectProvider进行按需注入:
@Componentpublic class MessageServiceConsumer {private final ObjectProvider<MessageService> messageServiceProvider;public MessageServiceConsumer(ObjectProvider<MessageService> messageServiceProvider) {this.messageServiceProvider = messageServiceProvider;}public void sendMessageByType(String messageType, String message) {try {MessageService messageService = messageServiceProvider.getIfAvailable() ;messageService.sendMessage(message);} catch (NoSuchBeanException e) {System.err.printf("不存在Bean, %s%n", e.getMessage()) ;} catch (NoUniqueBeanDefinitionException e) {System.err.printf("存在多个Bean: %s%n", e.getMessage()) ;}}}
案例二:获取指定类型的所有实例
接着上面示例,再定义一个MessageService实现类。
public class EmailMessageServiceImpl implements MessageService {public void sendMessage(String message) {System.out.printf("发送Email:%s%n", message);}}
使用ObjectProvider获取所有的实例Bean
public class MessageServiceConsumer2 {private final ObjectProvider<MessageService> messageServiceProvider;public MessageServiceConsumer2(ObjectProvider<MessageService> messageServiceProvider) {this.messageServiceProvider = messageServiceProvider;}public void sendMessage(String message) {// 通过orderedStream()方法获取所有匹配的实例Beanthis.messageServiceProvider.orderedStream().forEach(ms -> ms.sendMessage(message)) ;}}
orderStream() 方法返回的实例是有顺序的,我们可以为每个实例通过@Order注解定义优先级或者是实现Ordered接口,示例如下:
在MessageService实现类上添加Order注解
(2)public class EmailMessageServiceImpl implements MessageService {}(1)public class SmsMessageServiceImpl implements MessageService {}
@Order注解,值越小的优先级越高。所以通过orderStream方法返回的顺序将是SmsMessageServiceImpl 、EmailMessageServiceImpl 。
3. ObjectProvider原理
核心处理依赖注入是在DefaultListableBeanFactory#resolveDependency方法中
public class DefaultListableBeanFactory {public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}// ObjectProvider继承自ObjectFactory// 直接返回一个实现类DependencyObjectProvider,当在具体调用内部方法时else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}// ...}}
DependencyObjectProvider
private class DependencyObjectProvider implements BeanObjectProvider<Object> {public Object getObject() throws BeansException {// 只有调用具体的方法时才会再去DefaultListableBeanFactory中查找具体的类Object result = doResolveDependency(this.descriptor, this.beanName, null, null) ;}public Stream<Object> orderedStream() {// 参数决定了是否排序return resolveStream(true);}private Stream<Object> resolveStream(boolean ordered) {DependencyDescriptor descriptorToUse = new StreamDependencyDescriptor(this.descriptor, ordered);Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);return (result instanceof Stream ? (Stream<Object>) result : Stream.of(result));}}
完毕!!!
求关注、求转发



