All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.spring.util.BeanUtils Maven / Gradle / Ivy

There is a newer version: 1.0.11
Show newest version
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