com.alibaba.spring.util.BeanUtils Maven / Gradle / Ivy
package com.alibaba.spring.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors;
/**
* Bean Utilities Class
*
* @author Mercy
* @since 2017.01.13
*/
public abstract class BeanUtils {
private static final Log logger = LogFactory.getLog(BeanUtils.class);
private static final String[] EMPTY_BEAN_NAMES = new String[0];
/**
* Is Bean Present or not?
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @return If present , return true
, or false
*/
public static boolean isBeanPresent(ListableBeanFactory beanFactory,
Class> beanClass) {
return isBeanPresent(beanFactory, beanClass, false);
}
/**
* Is Bean Present or not?
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @param includingAncestors including ancestors or not
* @return If present , return true
, or false
*/
public static boolean isBeanPresent(ListableBeanFactory beanFactory,
Class> beanClass,
boolean includingAncestors) {
String[] beanNames = getBeanNames(beanFactory, beanClass, includingAncestors);
return !ObjectUtils.isEmpty(beanNames);
}
/**
* Is Bean Present or not?
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClassName The name of {@link Class} of Bean
* @param includingAncestors including ancestors or not
* @return If present , return true
, or false
*/
public static boolean isBeanPresent(ListableBeanFactory beanFactory,
String beanClassName,
boolean includingAncestors) {
boolean present = false;
ClassLoader classLoader = beanFactory.getClass().getClassLoader();
if (ClassUtils.isPresent(beanClassName, classLoader)) {
Class beanClass = ClassUtils.resolveClassName(beanClassName, classLoader);
present = isBeanPresent(beanFactory, beanClass, includingAncestors);
}
return present;
}
/**
* Is Bean Present or not?
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClassName The name of {@link Class} of Bean
* @return If present , return true
, or false
*/
public static boolean isBeanPresent(ListableBeanFactory beanFactory,
String beanClassName) {
return isBeanPresent(beanFactory, beanClassName, false);
}
/**
* Get Bean Names from {@link ConfigurableListableBeanFactory} by type.
*
* @param beanFactory {@link ConfigurableListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @return If found , return the array of Bean Names , or empty array.
*/
public static String[] getBeanNames(ConfigurableListableBeanFactory beanFactory, Class> beanClass) {
return getBeanNames(beanFactory, beanClass, false);
}
/**
* Get Bean Names from {@link ConfigurableListableBeanFactory} by type.
*
* @param beanFactory {@link ConfigurableListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @param includingAncestors including ancestors or not
* @return If found , return the array of Bean Names , or empty array.
*/
public static String[] getBeanNames(ConfigurableListableBeanFactory beanFactory, Class> beanClass,
boolean includingAncestors) {
Set beanNames = new LinkedHashSet();
beanNames.addAll(doGetBeanNames(beanFactory, beanClass));
if (includingAncestors) {
BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
if (parentBeanFactory instanceof ConfigurableListableBeanFactory) {
ConfigurableListableBeanFactory configurableListableBeanFactory =
(ConfigurableListableBeanFactory) parentBeanFactory;
String[] parentBeanNames = getBeanNames(configurableListableBeanFactory, beanClass, includingAncestors);
beanNames.addAll(Arrays.asList(parentBeanNames));
}
}
return StringUtils.toStringArray(beanNames);
}
/**
* Get Bean Names from {@link ListableBeanFactory} by type.
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @return If found , return the array of Bean Names , or empty array.
*/
public static String[] getBeanNames(ListableBeanFactory beanFactory, Class> beanClass) {
return getBeanNames(beanFactory, beanClass, false);
}
/**
* Get Bean Names from {@link ListableBeanFactory} by type.
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @param includingAncestors including ancestors or not
* @return If found , return the array of Bean Names , or empty array.
*/
public static String[] getBeanNames(ListableBeanFactory beanFactory, Class> beanClass,
boolean includingAncestors) {
final BeanFactory actualBeanFactory;
if (beanFactory instanceof ConfigurableApplicationContext) {
ConfigurableApplicationContext applicationContext = ConfigurableApplicationContext.class.cast(beanFactory);
actualBeanFactory = applicationContext.getBeanFactory();
} else {
actualBeanFactory = beanFactory;
}
if (actualBeanFactory instanceof ConfigurableListableBeanFactory) {
return getBeanNames((ConfigurableListableBeanFactory) actualBeanFactory, beanClass, includingAncestors);
}
return EMPTY_BEAN_NAMES;
}
private static Class> getFactoryBeanType(ConfigurableListableBeanFactory beanFactory,
BeanDefinition factoryBeanDefinition) {
BeanDefinition actualFactoryBeanDefinition = factoryBeanDefinition;
final List> beanClasses = new ArrayList>(1);
ClassLoader classLoader = beanFactory.getBeanClassLoader();
String factoryBeanClassName = actualFactoryBeanDefinition.getBeanClassName();
if (StringUtils.isEmpty(factoryBeanClassName)) {
String factoryBeanName = factoryBeanDefinition.getFactoryBeanName();
actualFactoryBeanDefinition = beanFactory.getBeanDefinition(factoryBeanName);
factoryBeanClassName = actualFactoryBeanDefinition.getBeanClassName();
}
if (StringUtils.hasText(factoryBeanClassName)) {
Class> factoryBeanClass = resolveBeanType(factoryBeanClassName, classLoader);
final String factoryMethodName = factoryBeanDefinition.getFactoryMethodName();
// @Configuration only allow one method FactoryBean
ReflectionUtils.doWithMethods(factoryBeanClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
beanClasses.add(method.getReturnType());
}
}, new ReflectionUtils.MethodFilter() {
@Override
public boolean matches(Method method) {
return factoryMethodName.equals(method.getName());
}
});
}
return beanClasses.isEmpty() ? null : beanClasses.get(0);
}
private static Class> resolveBeanType(ConfigurableListableBeanFactory beanFactory, BeanDefinition beanDefinition) {
String factoryBeanName = beanDefinition.getFactoryBeanName();
ClassLoader classLoader = beanFactory.getBeanClassLoader();
Class> beanType = null;
if (StringUtils.hasText(factoryBeanName)) {
beanType = getFactoryBeanType(beanFactory, beanDefinition);
}
if (beanType == null) {
String beanClassName = beanDefinition.getBeanClassName();
if (StringUtils.hasText(beanClassName)) {
beanType = resolveBeanType(beanClassName, classLoader);
}
}
if (beanType == null) {
if (logger.isErrorEnabled()) {
String message = beanDefinition + " can't be resolved bean type!";
logger.error(message);
}
}
return beanType;
}
/**
* Get Bean names from {@link ConfigurableListableBeanFactory} by type
*
* @param beanFactory {@link ConfigurableListableBeanFactory}
* @param beanType The {@link Class type} of Bean
* @return the array of bean names.
*/
protected static Set doGetBeanNames(ConfigurableListableBeanFactory beanFactory, Class> beanType) {
String[] allBeanNames = beanFactory.getBeanDefinitionNames();
Set beanNames = new LinkedHashSet();
for (String beanName : allBeanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
Class> beanClass = resolveBeanType(beanFactory, beanDefinition);
if (beanClass != null && ClassUtils.isAssignable(beanType, beanClass)) {
beanNames.add(beanName);
}
}
return Collections.unmodifiableSet(beanNames);
}
/**
* Resolve Bean Type
*
* @param beanClassName the class name of Bean
* @param classLoader {@link ClassLoader}
* @return Bean type if can be resolved , or return null
.
*/
public static Class> resolveBeanType(String beanClassName, ClassLoader classLoader) {
if (!StringUtils.hasText(beanClassName)) {
return null;
}
Class> beanType = null;
try {
beanType = ClassUtils.resolveClassName(beanClassName, classLoader);
beanType = ClassUtils.getUserClass(beanType);
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
return beanType;
}
/**
* Get Optional Bean by {@link Class} including ancestors(BeanFactory).
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @param includingAncestors including ancestors or not
* @param The {@link Class} of Bean
* @return Bean object if found , or return null
.
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
* @see BeanFactoryUtils#beanOfTypeIncludingAncestors(ListableBeanFactory, Class)
*/
public static T getOptionalBean(ListableBeanFactory beanFactory, Class beanClass,
boolean includingAncestors) throws BeansException {
String[] beanNames = getBeanNames(beanFactory, beanClass, includingAncestors);
if (ObjectUtils.isEmpty(beanNames)) {
if (logger.isDebugEnabled()) {
logger.debug("The bean [ class : " + beanClass.getName() + " ] can't be found ");
}
return null;
}
T bean = null;
try {
bean = includingAncestors ?
beanOfTypeIncludingAncestors(beanFactory, beanClass) :
beanFactory.getBean(beanClass);
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error(e.getMessage(), e);
}
}
return bean;
}
/**
* Get Optional Bean by {@link Class}.
*
* @param beanFactory {@link ListableBeanFactory}
* @param beanClass The {@link Class} of Bean
* @param The {@link Class} of Bean
* @return Bean object if found , or return null
.
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
*/
public static T getOptionalBean(ListableBeanFactory beanFactory, Class beanClass) throws BeansException {
return getOptionalBean(beanFactory, beanClass, false);
}
/**
* Get all sorted Beans of {@link ListableBeanFactory} in specified bean type.
*
* @param beanFactory {@link ListableBeanFactory}
* @param type bean type
* @param bean type
* @return all sorted Beans
*/
public static List getSortedBeans(ListableBeanFactory beanFactory, Class type) {
Map beansOfType = BeanFactoryUtils.beansOfTypeIncludingAncestors(beanFactory, type);
List beansList = new ArrayList(beansOfType.values());
AnnotationAwareOrderComparator.sort(beansList);
return Collections.unmodifiableList(beansList);
}
/**
* Sort Beans {@link Map} via {@link AnnotationAwareOrderComparator#sort(List)} rule
*
* @param beansMap Beans {@link Map}
* @param the type of Bean
* @return sorted Beans {@link Map}
*/
public static Map sort(final Map beansMap) {
Map unmodifiableBeansMap = Collections.unmodifiableMap(beansMap);
List> namingBeans = new ArrayList>(unmodifiableBeansMap.size());
for (Map.Entry entry : unmodifiableBeansMap.entrySet()) {
String beanName = entry.getKey();
T bean = entry.getValue();
NamingBean namingBean = new NamingBean(beanName, bean);
namingBeans.add(namingBean);
}
AnnotationAwareOrderComparator.sort(namingBeans);
Map sortedBeansMap = new LinkedHashMap(beansMap.size());
for (NamingBean namingBean : namingBeans) {
sortedBeansMap.put(namingBean.name, namingBean.bean);
}
return sortedBeansMap;
}
static class NamingBean extends AnnotationAwareOrderComparator implements Comparable, Ordered {
private final String name;
private final T bean;
NamingBean(String name, T bean) {
this.name = name;
this.bean = bean;
}
@Override
public int compareTo(NamingBean o) {
return compare(this, o);
}
@Override
public int getOrder() {
return getOrder(bean);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy