1
1
/*
2
- * Copyright 2002-2018 the original author or authors.
2
+ * Copyright 2002-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
22
22
import java .util .stream .Stream ;
23
23
24
24
import org .springframework .beans .BeansException ;
25
+ import org .springframework .core .OrderComparator ;
25
26
import org .springframework .lang .Nullable ;
26
27
27
28
/**
28
29
* A variant of {@link ObjectFactory} designed specifically for injection points,
29
30
* allowing for programmatic optionality and lenient not-unique handling.
30
31
*
32
+ * <p>In a {@link BeanFactory} environment, every {@code ObjectProvider} obtained
33
+ * from the factory will be bound to its {@code BeanFactory} for a specific bean
34
+ * type, matching all provider calls against factory-registered bean definitions.
35
+ *
31
36
* <p>As of 5.1, this interface extends {@link Iterable} and provides {@link Stream}
32
37
* support. It can be therefore be used in {@code for} loops, provides {@link #forEach}
33
38
* iteration and allows for collection-style {@link #stream} access.
34
39
*
40
+ * <p>As of 6.2, this interface declares default implementations for all methods.
41
+ * This makes it easier to implement in a custom fashion, e.g. for unit tests.
42
+ * For typical purposes, implement {@link #stream()} to enable all other methods.
43
+ * Alternatively, you may implement the specific methods that your callers expect,
44
+ * e.g. just {@link #getObject()} or {@link #getIfAvailable()}.
45
+ *
35
46
* @author Juergen Hoeller
36
47
* @since 4.3
37
48
* @param <T> the object type
40
51
*/
41
52
public interface ObjectProvider <T > extends ObjectFactory <T >, Iterable <T > {
42
53
54
+ @ Override
55
+ default T getObject () throws BeansException {
56
+ Iterator <T > it = iterator ();
57
+ if (!it .hasNext ()) {
58
+ throw new NoSuchBeanDefinitionException (Object .class );
59
+ }
60
+ T result = it .next ();
61
+ if (it .hasNext ()) {
62
+ throw new NoUniqueBeanDefinitionException (Object .class , 2 , "more than 1 matching bean" );
63
+ }
64
+ return result ;
65
+ }
66
+
43
67
/**
44
68
* Return an instance (possibly shared or independent) of the object
45
69
* managed by this factory.
@@ -50,7 +74,10 @@ public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
50
74
* @throws BeansException in case of creation errors
51
75
* @see #getObject()
52
76
*/
53
- T getObject (Object ... args ) throws BeansException ;
77
+ default T getObject (Object ... args ) throws BeansException {
78
+ throw new UnsupportedOperationException ("Retrieval with arguments not supported -" +
79
+ "for custom ObjectProvider classes, implement getObject(Object...) for your purposes" );
80
+ }
54
81
55
82
/**
56
83
* Return an instance (possibly shared or independent) of the object
@@ -60,7 +87,17 @@ public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
60
87
* @see #getObject()
61
88
*/
62
89
@ Nullable
63
- T getIfAvailable () throws BeansException ;
90
+ default T getIfAvailable () throws BeansException {
91
+ try {
92
+ return getObject ();
93
+ }
94
+ catch (NoUniqueBeanDefinitionException ex ) {
95
+ throw ex ;
96
+ }
97
+ catch (NoSuchBeanDefinitionException ex ) {
98
+ return null ;
99
+ }
100
+ }
64
101
65
102
/**
66
103
* Return an instance (possibly shared or independent) of the object
@@ -103,7 +140,14 @@ default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
103
140
* @see #getObject()
104
141
*/
105
142
@ Nullable
106
- T getIfUnique () throws BeansException ;
143
+ default T getIfUnique () throws BeansException {
144
+ try {
145
+ return getObject ();
146
+ }
147
+ catch (NoSuchBeanDefinitionException ex ) {
148
+ return null ;
149
+ }
150
+ }
107
151
108
152
/**
109
153
* Return an instance (possibly shared or independent) of the object
@@ -157,7 +201,8 @@ default Iterator<T> iterator() {
157
201
* @see #orderedStream()
158
202
*/
159
203
default Stream <T > stream () {
160
- throw new UnsupportedOperationException ("Multi element access not supported" );
204
+ throw new UnsupportedOperationException ("Element access not supported - " +
205
+ "for custom ObjectProvider classes, implement stream() to enable all other methods" );
161
206
}
162
207
163
208
/**
@@ -168,12 +213,16 @@ default Stream<T> stream() {
168
213
* and in case of annotation-based configuration also considering the
169
214
* {@link org.springframework.core.annotation.Order} annotation,
170
215
* analogous to multi-element injection points of list/array type.
216
+ * <p>The default method applies an {@link OrderComparator} to the
217
+ * {@link #stream()} method. You may override this to apply an
218
+ * {@link org.springframework.core.annotation.AnnotationAwareOrderComparator}
219
+ * if necessary.
171
220
* @since 5.1
172
221
* @see #stream()
173
222
* @see org.springframework.core.OrderComparator
174
223
*/
175
224
default Stream <T > orderedStream () {
176
- throw new UnsupportedOperationException ( "Ordered element access not supported" );
225
+ return stream (). sorted ( OrderComparator . INSTANCE );
177
226
}
178
227
179
228
}
0 commit comments