DATAGEODE-326 - Add additional 'getOrderedStreamOfBeansByType(..)' utility method in SpringUtils.
This methods also returns beans in order based on bean's class type or bean definitions annotated with the @Order annotation in addition to beans implementing the Ordered interface. The difference between this method and the 'getBeansOfTypeOrdered(..)' method is that this method uses BeanFactory.getBeanProvider(:Class).orderedStream() internally whereas 'getBeansOfTypeOrdered(..)' uses ListableBeanFactory.getBeansOfType(..) with additional magic.
This commit is contained in:
@@ -30,9 +30,11 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
@@ -70,7 +72,7 @@ public abstract class SpringUtils {
|
||||
* @param beanName {@link String name} of the bean.
|
||||
* @param beanType {@link Class type} of the bean.
|
||||
* @return a boolean value indicating whether the {@link BeanFactory Spring container} contains a bean
|
||||
* matching by both {@link String name} as well as {@link Class type}.
|
||||
* matching by both {@link String name} and {@link Class type}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see java.lang.Class
|
||||
* @see java.lang.String
|
||||
@@ -79,7 +81,16 @@ public abstract class SpringUtils {
|
||||
return beanFactory.containsBean(beanName) && beanFactory.isTypeMatch(beanName, beanType);
|
||||
}
|
||||
|
||||
public static BeanDefinition addDependsOn(BeanDefinition beanDefinition, String... beanNames) {
|
||||
/**
|
||||
* Adds an array of bean dependencies (by name) to the given {@link BeanDefinition}.
|
||||
*
|
||||
* @param beanDefinition {@link BeanDefinition} to add the bean dependencies to.
|
||||
* @param beanNames {@link String} array containing names of beans to which the {@link BeanDefinition}
|
||||
* has a dependency.
|
||||
* @return the given {@link BeanDefinition}.
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition
|
||||
*/
|
||||
public static BeanDefinition addDependsOn(@NonNull BeanDefinition beanDefinition, @Nullable String... beanNames) {
|
||||
|
||||
List<String> dependsOnList = new ArrayList<>();
|
||||
|
||||
@@ -90,6 +101,18 @@ public abstract class SpringUtils {
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of beans by the given {@link Class type} in order.
|
||||
*
|
||||
* @param <T> {@link Class type} of the bean.
|
||||
* @param beanFactory {@link ConfigurableListableBeanFactory Spring container} used to acquire the ordered beans.
|
||||
* @param beanType {@link Class type} of beans to acquire.
|
||||
* @return a {@link List} of beans of the given {@link Class type} in order.
|
||||
* @see #getBeansOfTypeOrdered(ConfigurableListableBeanFactory, Class, boolean, boolean)
|
||||
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
||||
* @see java.lang.Class
|
||||
* @see java.util.List
|
||||
*/
|
||||
@NonNull
|
||||
public static <T> List<T> getBeansOfTypeOrdered(@NonNull ConfigurableListableBeanFactory beanFactory,
|
||||
@NonNull Class<T> beanType) {
|
||||
@@ -97,6 +120,19 @@ public abstract class SpringUtils {
|
||||
return getBeansOfTypeOrdered(beanFactory, beanType, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of beans by the given {@link Class type} in order.
|
||||
*
|
||||
* @param <T> {@link Class type} of the bean.
|
||||
* @param beanFactory {@link ConfigurableListableBeanFactory Spring container} used to acquire the ordered beans.
|
||||
* @param beanType {@link Class type} of beans to acquire.
|
||||
* @param includeNonSingletons boolean indicating whether to include non-Singleton beans from the Spring container.
|
||||
* @param allowEagerInit boolean indicating whether to eagerly initialize {@link FactoryBean FactoryBeans}.
|
||||
* @return a {@link List} of beans of the given {@link Class type} in order.
|
||||
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory
|
||||
* @see java.lang.Class
|
||||
* @see java.util.List
|
||||
*/
|
||||
@NonNull
|
||||
public static <T> List<T> getBeansOfTypeOrdered(@NonNull ConfigurableListableBeanFactory beanFactory,
|
||||
@NonNull Class<T> beanType, boolean includeNonSingletons, boolean allowEagerInit) {
|
||||
@@ -104,13 +140,13 @@ public abstract class SpringUtils {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
Assert.notNull(beanType, "Bean type must not be null");
|
||||
|
||||
Map<String, T> beansOfType = beanFactory.getBeansOfType(beanType, includeNonSingletons, allowEagerInit);
|
||||
Map<String, T> beansOfType =
|
||||
CollectionUtils.nullSafeMap(beanFactory.getBeansOfType(beanType, includeNonSingletons, allowEagerInit));
|
||||
|
||||
Set<String> beanNamesOfType = new HashSet<>(beansOfType.keySet());
|
||||
|
||||
// Handles @Order annotated beans and beans implementing the Ordered interface
|
||||
List<OrderedBeanWrapper<T>> orderedBeansOfType =
|
||||
CollectionUtils.nullSafeMap(beansOfType).entrySet().stream()
|
||||
List<OrderedBeanWrapper<T>> orderedBeansOfType = beansOfType.entrySet().stream()
|
||||
.map(SpringUtils::toOrderedBeanWrapper)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
@@ -132,6 +168,7 @@ public abstract class SpringUtils {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// No Javadoc
|
||||
private static <T> List<OrderedBeanWrapper<T>> orderUnorderedBeans(@NonNull ConfigurableListableBeanFactory beanFactory,
|
||||
@NonNull Map<String, T> beansOfType, @NonNull Set<String> unorderedBeanNames) {
|
||||
|
||||
@@ -157,6 +194,7 @@ public abstract class SpringUtils {
|
||||
return orderedBeanWrappers;
|
||||
}
|
||||
|
||||
// No Javadoc
|
||||
@Nullable
|
||||
private static <T> OrderedBeanWrapper<T> toOrderedBeanWrapper(@NonNull Map.Entry<String, T> beanEntry) {
|
||||
|
||||
@@ -174,6 +212,25 @@ public abstract class SpringUtils {
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bean of the given {@link Class type} in an ordered {@link Stream}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the beans.
|
||||
* @param beanFactory {@link BeanFactory} from which to acquire the beans.
|
||||
* @param beanType {@link Class type} of the beans.
|
||||
* @return an ordered {@link Stream} of beans from the {@link BeanFactory} of the given {@link Class type}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see java.util.stream.Stream
|
||||
* @see java.lang.Class
|
||||
*/
|
||||
public static <T> Stream<T> getOrderedStreamOfBeansByType(BeanFactory beanFactory, Class<T> beanType) {
|
||||
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
Assert.notNull(beanType,"Bean type must not be null");
|
||||
|
||||
return beanFactory.getBeanProvider(beanType).orderedStream();
|
||||
}
|
||||
|
||||
public static Optional<Object> getPropertyValue(BeanDefinition beanDefinition, String propertyName) {
|
||||
|
||||
return Optional.ofNullable(beanDefinition)
|
||||
@@ -308,9 +365,9 @@ public abstract class SpringUtils {
|
||||
Assert.notNull(bean, "Bean must not be null");
|
||||
Assert.hasText(beanName, "Bean name is required");
|
||||
|
||||
this.order = order;
|
||||
this.bean = bean;
|
||||
this.beanName = beanName;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -42,7 +43,9 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.data.gemfire.util.SpringUtils;
|
||||
import org.springframework.data.gemfire.util.StreamUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -128,6 +131,18 @@ public class ApplicationContextBeanOrderingIntegrationTests {
|
||||
.containsExactly("A", "B", "C", "D", "U", "X", "Y", "Z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expectBeansToBeOrderedByOrderAnnotationAndOrderedInterfaceUsingBeanProviderOrderedStream() {
|
||||
|
||||
List<String> beanNames = this.applicationContext.getBeanProvider(NamedBean.class).orderedStream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(beanNames)
|
||||
.describedAs("Expected [Y, X, Z, B, C, A, D, U]; but was %s", beanNames)
|
||||
.containsExactly("Y", "X", "Z", "B", "C", "A", "D", "U");
|
||||
}
|
||||
|
||||
/**
|
||||
* 4. Test Fails (of course)!
|
||||
*
|
||||
@@ -215,10 +230,14 @@ public class ApplicationContextBeanOrderingIntegrationTests {
|
||||
@Test
|
||||
public void expectBeansToBeOrderedByOrderAnnotationAndOrderedInterfaceUsingSpringUtils() {
|
||||
|
||||
List<String> beanNames =
|
||||
SpringUtils.getBeansOfTypeOrdered(this.applicationContext.getBeanFactory(), NamedBean.class).stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList());
|
||||
List<NamedBean> orderedBeans = CollectionUtils
|
||||
.nullSafeList(SpringUtils.getBeansOfTypeOrdered(this.applicationContext.getBeanFactory(), NamedBean.class));
|
||||
|
||||
Stream<NamedBean> orderedBeanStream = StreamUtils.nullSafeStream(orderedBeans.stream());
|
||||
|
||||
List<String> beanNames = orderedBeanStream
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(beanNames)
|
||||
.describedAs("Expected [Y, X, Z, B, C, A, D, U]; but was %s", beanNames)
|
||||
|
||||
Reference in New Issue
Block a user