001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans.factory;
018
019import java.util.Iterator;
020import java.util.function.Consumer;
021import java.util.function.Supplier;
022import java.util.stream.Stream;
023
024import org.springframework.beans.BeansException;
025import org.springframework.lang.Nullable;
026
027/**
028 * A variant of {@link ObjectFactory} designed specifically for injection points,
029 * allowing for programmatic optionality and lenient not-unique handling.
030 *
031 * <p>As of 5.1, this interface extends {@link Iterable} and provides {@link Stream}
032 * support. It can be therefore be used in {@code for} loops, provides {@link #forEach}
033 * iteration and allows for collection-style {@link #stream} access.
034 *
035 * @author Juergen Hoeller
036 * @since 4.3
037 * @param <T> the object type
038 * @see BeanFactory#getBeanProvider
039 * @see org.springframework.beans.factory.annotation.Autowired
040 */
041public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
042
043        /**
044         * Return an instance (possibly shared or independent) of the object
045         * managed by this factory.
046         * <p>Allows for specifying explicit construction arguments, along the
047         * lines of {@link BeanFactory#getBean(String, Object...)}.
048         * @param args arguments to use when creating a corresponding instance
049         * @return an instance of the bean
050         * @throws BeansException in case of creation errors
051         * @see #getObject()
052         */
053        T getObject(Object... args) throws BeansException;
054
055        /**
056         * Return an instance (possibly shared or independent) of the object
057         * managed by this factory.
058         * @return an instance of the bean, or {@code null} if not available
059         * @throws BeansException in case of creation errors
060         * @see #getObject()
061         */
062        @Nullable
063        T getIfAvailable() throws BeansException;
064
065        /**
066         * Return an instance (possibly shared or independent) of the object
067         * managed by this factory.
068         * @param defaultSupplier a callback for supplying a default object
069         * if none is present in the factory
070         * @return an instance of the bean, or the supplied default object
071         * if no such bean is available
072         * @throws BeansException in case of creation errors
073         * @since 5.0
074         * @see #getIfAvailable()
075         */
076        default T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {
077                T dependency = getIfAvailable();
078                return (dependency != null ? dependency : defaultSupplier.get());
079        }
080
081        /**
082         * Consume an instance (possibly shared or independent) of the object
083         * managed by this factory, if available.
084         * @param dependencyConsumer a callback for processing the target object
085         * if available (not called otherwise)
086         * @throws BeansException in case of creation errors
087         * @since 5.0
088         * @see #getIfAvailable()
089         */
090        default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
091                T dependency = getIfAvailable();
092                if (dependency != null) {
093                        dependencyConsumer.accept(dependency);
094                }
095        }
096
097        /**
098         * Return an instance (possibly shared or independent) of the object
099         * managed by this factory.
100         * @return an instance of the bean, or {@code null} if not available or
101         * not unique (i.e. multiple candidates found with none marked as primary)
102         * @throws BeansException in case of creation errors
103         * @see #getObject()
104         */
105        @Nullable
106        T getIfUnique() throws BeansException;
107
108        /**
109         * Return an instance (possibly shared or independent) of the object
110         * managed by this factory.
111         * @param defaultSupplier a callback for supplying a default object
112         * if no unique candidate is present in the factory
113         * @return an instance of the bean, or the supplied default object
114         * if no such bean is available or if it is not unique in the factory
115         * (i.e. multiple candidates found with none marked as primary)
116         * @throws BeansException in case of creation errors
117         * @since 5.0
118         * @see #getIfUnique()
119         */
120        default T getIfUnique(Supplier<T> defaultSupplier) throws BeansException {
121                T dependency = getIfUnique();
122                return (dependency != null ? dependency : defaultSupplier.get());
123        }
124
125        /**
126         * Consume an instance (possibly shared or independent) of the object
127         * managed by this factory, if unique.
128         * @param dependencyConsumer a callback for processing the target object
129         * if unique (not called otherwise)
130         * @throws BeansException in case of creation errors
131         * @since 5.0
132         * @see #getIfAvailable()
133         */
134        default void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {
135                T dependency = getIfUnique();
136                if (dependency != null) {
137                        dependencyConsumer.accept(dependency);
138                }
139        }
140
141        /**
142         * Return an {@link Iterator} over all matching object instances,
143         * without specific ordering guarantees (but typically in registration order).
144         * @since 5.1
145         * @see #stream()
146         */
147        @Override
148        default Iterator<T> iterator() {
149                return stream().iterator();
150        }
151
152        /**
153         * Return a sequential {@link Stream} over all matching object instances,
154         * without specific ordering guarantees (but typically in registration order).
155         * @since 5.1
156         * @see #iterator()
157         * @see #orderedStream()
158         */
159        default Stream<T> stream() {
160                throw new UnsupportedOperationException("Multi element access not supported");
161        }
162
163        /**
164         * Return a sequential {@link Stream} over all matching object instances,
165         * pre-ordered according to the factory's common order comparator.
166         * <p>In a standard Spring application context, this will be ordered
167         * according to {@link org.springframework.core.Ordered} conventions,
168         * and in case of annotation-based configuration also considering the
169         * {@link org.springframework.core.annotation.Order} annotation,
170         * analogous to multi-element injection points of list/array type.
171         * @since 5.1
172         * @see #stream()
173         * @see org.springframework.core.OrderComparator
174         */
175        default Stream<T> orderedStream() {
176                throw new UnsupportedOperationException("Ordered element access not supported");
177        }
178
179}