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

io.microsphere.spring.util.BeanUtils Maven / Gradle / Ivy

package io.microsphere.spring.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
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.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationStartupAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static io.microsphere.spring.util.ApplicationContextUtils.asConfigurableApplicationContext;
import static io.microsphere.spring.util.BeanFactoryUtils.asBeanDefinitionRegistry;
import static io.microsphere.spring.util.BeanFactoryUtils.asConfigurableBeanFactory;
import static io.microsphere.util.ClassLoaderUtils.isPresent;
import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;
import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors;
import static org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors;
import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.generateBeanName;

/**
 * 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];

    private static final boolean APPLICATION_STARTUP_CLASS_PRESENT = isPresent("org.springframework.core.metrics.ApplicationStartup", null);

    /**
     * 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);

    }

    /**
     * Is Bean Present or not by the specified name and class
     *
     * @param beanFactory {@link BeanFactory}
     * @param beanName    The bean name
     * @param beanClass   The bean class
     * @return If present , return true , or false
     * @since 1.0.0
     */
    public static boolean isBeanPresent(BeanFactory beanFactory, String beanName, Class beanClass) throws NullPointerException {
        return beanFactory.containsBean(beanName) && beanFactory.isTypeMatch(beanName, beanClass);
    }

    /**
     * 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) {
        // Issue : https://github.com/alibaba/spring-context-support/issues/22
        if (includingAncestors) {
            return beanNamesForTypeIncludingAncestors(beanFactory, beanClass, true, false);
        } else {
            return beanFactory.getBeanNamesForType(beanClass, true, false);
        }
    }

    /**
     * Get Bean Names from {@link ListableBeanFactory} 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 ListableBeanFactory} 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) {
        return getBeanNames((ListableBeanFactory) beanFactory, beanClass, includingAncestors);
    }


    /**
     * 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 the bean via the specified bean name and type if available
     *
     * @param beanFactory {@link BeanFactory}
     * @param beanName    the bean name
     * @param beanType    the class of bean
     * @param          the bean type
     * @return the bean if available, or null
     * @throws BeansException in case of creation errors
     * @since 1.0.0
     */
    public static  T getBeanIfAvailable(BeanFactory beanFactory, String beanName, Class beanType) throws BeansException {
        if (isBeanPresent(beanFactory, beanName, beanType)) {
            return beanFactory.getBean(beanName, beanType);
        }

        if (logger.isDebugEnabled()) {
            logger.debug(format("The bean[name : %s , type : %s] can't be found in Spring BeanFactory", beanName, beanType.getName()));
        }
        return null;
    }


    /**
     * 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 = beansOfTypeIncludingAncestors(beanFactory, type);
        List beansList = new ArrayList(beansOfType.values());
        AnnotationAwareOrderComparator.sort(beansList);
        return unmodifiableList(beansList);
    }

    /**
     * Invoke Spring Bean interfaces in order:
     * 
    *
  • {@link BeanNameAware}
  • *
  • {@link BeanClassLoaderAware}
  • *
  • {@link BeanFactoryAware}
  • *
  • {@link EnvironmentAware}
  • *
  • {@link EmbeddedValueResolverAware}
  • *
  • {@link ResourceLoaderAware}
  • *
  • {@link ApplicationEventPublisherAware}
  • *
  • {@link MessageSourceAware}
  • *
  • {@link ApplicationStartupAware} (Spring Framework 5.3+)
  • *
  • {@link ApplicationContextAware}
  • *
  • {@link InitializingBean}
  • *
* * @param bean the bean * @param context {@link ApplicationContext} */ public static void invokeBeanInterfaces(Object bean, ApplicationContext context) { ConfigurableApplicationContext configurableApplicationContext = asConfigurableApplicationContext(context); invokeBeanInterfaces(bean, configurableApplicationContext); } /** * Invoke Spring Bean interfaces in order: *
    *
  • {@link BeanNameAware}
  • *
  • {@link BeanClassLoaderAware}
  • *
  • {@link BeanFactoryAware}
  • *
  • {@link EnvironmentAware}
  • *
  • {@link EmbeddedValueResolverAware}
  • *
  • {@link ResourceLoaderAware}
  • *
  • {@link ApplicationEventPublisherAware}
  • *
  • {@link MessageSourceAware}
  • *
  • {@link ApplicationStartupAware} (Spring Framework 5.3+)
  • *
  • {@link ApplicationContextAware}
  • *
  • {@link InitializingBean}
  • *
* * @param bean the bean * @param context {@link ConfigurableApplicationContext} * @see #invokeBeanInterfaces(Object, ApplicationContext) * @see #invokeAwareInterfaces(Object, ApplicationContext) * @see #invokeInitializingBean(Object) */ public static void invokeBeanInterfaces(Object bean, ConfigurableApplicationContext context) { invokeAwareInterfaces(bean, context); try { invokeInitializingBean(bean); } catch (Exception e) { throw new RuntimeException(e); } } public static void invokeInitializingBean(Object bean) throws Exception { if (bean instanceof InitializingBean) { ((InitializingBean) bean).afterPropertiesSet(); } } /** * Invoke the {@link Aware} interfaces in order : *
    *
  • {@link BeanNameAware}
  • *
  • {@link BeanClassLoaderAware}
  • *
  • {@link BeanFactoryAware}
  • *
*

* if the argument beanFactory is an instance of {@link ApplicationContext}, the more {@link Aware} interfaces * will be involved : *

    *
  • {@link EnvironmentAware}
  • *
  • {@link EmbeddedValueResolverAware}
  • *
  • {@link ResourceLoaderAware}
  • *
  • {@link ApplicationEventPublisherAware}
  • *
  • {@link MessageSourceAware}
  • *
  • {@link ApplicationStartupAware} (Spring Framework 5.3+)
  • *
  • {@link ApplicationContextAware}
  • *
* * @param bean the bean * @param beanFactory {@link BeanFactory} */ public static void invokeAwareInterfaces(Object bean, BeanFactory beanFactory) { invokeAwareInterfaces(bean, beanFactory, asConfigurableBeanFactory(beanFactory)); } /** * Invoke the {@link Aware} interfaces in order : *
    *
  • {@link BeanNameAware}
  • *
  • {@link BeanClassLoaderAware}
  • *
  • {@link BeanFactoryAware}
  • *
*

* if the argument beanFactory is an instance of {@link ApplicationContext}, the more {@link Aware} interfaces * will be involved : *

    *
  • {@link EnvironmentAware}
  • *
  • {@link EmbeddedValueResolverAware}
  • *
  • {@link ResourceLoaderAware}
  • *
  • {@link ApplicationEventPublisherAware}
  • *
  • {@link MessageSourceAware}
  • *
  • {@link ApplicationStartupAware} (Spring Framework 5.3+)
  • *
  • {@link ApplicationContextAware}
  • *
* * @param bean the bean * @param beanFactory {@link ConfigurableBeanFactory} */ public static void invokeAwareInterfaces(Object bean, ConfigurableBeanFactory beanFactory) { invokeAwareInterfaces(bean, beanFactory, beanFactory); } /** * Invoke the {@link Aware} interfaces in order : *
    *
  • {@link BeanNameAware}
  • *
  • {@link BeanClassLoaderAware}
  • *
  • {@link BeanFactoryAware}
  • *
*

* if the argument beanFactory is an instance of {@link ApplicationContext}, the more {@link Aware} interfaces * will be involved : *

    *
  • {@link EnvironmentAware}
  • *
  • {@link EmbeddedValueResolverAware}
  • *
  • {@link ResourceLoaderAware}
  • *
  • {@link ApplicationEventPublisherAware}
  • *
  • {@link MessageSourceAware}
  • *
  • {@link ApplicationStartupAware} (Spring Framework 5.3+)
  • *
  • {@link ApplicationContextAware}
  • *
* * @param bean * @param beanFactory * @param configurableBeanFactory */ static void invokeAwareInterfaces(Object bean, BeanFactory beanFactory, @Nullable ConfigurableBeanFactory configurableBeanFactory) { if (beanFactory instanceof ApplicationContext) { invokeAwareInterfaces(bean, (ApplicationContext) beanFactory); } else { invokeBeanFactoryAwareInterfaces(bean, beanFactory, configurableBeanFactory); } } /** * @see AbstractAutowireCapableBeanFactory#invokeAwareMethods(String, Object) */ static void invokeBeanFactoryAwareInterfaces(Object bean, BeanFactory beanFactory, @Nullable ConfigurableBeanFactory configurableBeanFactory) { invokeBeanNameAware(bean, beanFactory); invokeBeanClassLoaderAware(bean, configurableBeanFactory); invokeBeanFactoryAware(bean, beanFactory); } static void invokeBeanNameAware(Object bean, BeanFactory beanFactory) { if (bean instanceof BeanNameAware) { BeanDefinitionRegistry registry = asBeanDefinitionRegistry(beanFactory); BeanDefinition beanDefinition = rootBeanDefinition(bean.getClass()).getBeanDefinition(); String beanName = generateBeanName(beanDefinition, registry); ((BeanNameAware) bean).setBeanName(beanName); } } public static void invokeBeanNameAware(Object bean, String beanName) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } } static void invokeBeanFactoryAware(Object bean, BeanFactory beanFactory) { if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(beanFactory); } } static void invokeBeanClassLoaderAware(Object bean, @Nullable ConfigurableBeanFactory configurableBeanFactory) { if (bean instanceof BeanClassLoaderAware && configurableBeanFactory != null) { ClassLoader classLoader = configurableBeanFactory.getBeanClassLoader(); ((BeanClassLoaderAware) bean).setBeanClassLoader(classLoader); } } /** * Invoke {@link Aware} interfaces if the given bean implements *

* Current implementation keeps the order of invocation {@link Aware Aware interfaces}: *

    *
  • {@link BeanNameAware}
  • *
  • {@link BeanClassLoaderAware}
  • *
  • {@link BeanFactoryAware}
  • *
  • {@link EnvironmentAware}
  • *
  • {@link EmbeddedValueResolverAware}
  • *
  • {@link ResourceLoaderAware}
  • *
  • {@link ApplicationEventPublisherAware}
  • *
  • {@link MessageSourceAware}
  • *
  • {@link ApplicationStartupAware} (Spring Framework 5.3+)
  • *
  • {@link ApplicationContextAware}
  • *
* * @param bean the bean * @param context {@link ApplicationContext} * @see #invokeAwareInterfaces(Object, BeanFactory) * @see org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces(Object) * @see AbstractAutowireCapableBeanFactory#invokeAwareMethods(String, Object) */ static void invokeAwareInterfaces(Object bean, ApplicationContext context) { invokeAwareInterfaces(bean, context, asConfigurableApplicationContext(context)); } /** * Invoke {@link Aware} interfaces if the given bean implements *

* Current implementation keeps the order of invocation {@link Aware Aware interfaces}: *

    *
  • {@link BeanNameAware}
  • *
  • {@link BeanClassLoaderAware}
  • *
  • {@link BeanFactoryAware}
  • *
  • {@link EnvironmentAware}
  • *
  • {@link EmbeddedValueResolverAware}
  • *
  • {@link ResourceLoaderAware}
  • *
  • {@link ApplicationEventPublisherAware}
  • *
  • {@link MessageSourceAware}
  • *
  • {@link ApplicationStartupAware} (Spring Framework 5.3+)
  • *
  • {@link ApplicationContextAware}
  • *
* * @param bean the bean * @param context {@link ApplicationContext} * @see #invokeAwareInterfaces(Object, BeanFactory) * @see org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces(Object) * @see AbstractAutowireCapableBeanFactory#invokeAwareMethods(String, Object) */ public static void invokeAwareInterfaces(Object bean, ConfigurableApplicationContext context) { invokeAwareInterfaces(bean, context, context); } static void invokeAwareInterfaces(Object bean, ApplicationContext context, @Nullable ConfigurableApplicationContext applicationContext) { if (bean == null || context == null) { return; } ConfigurableListableBeanFactory beanFactory = applicationContext != null ? applicationContext.getBeanFactory() : null; invokeBeanFactoryAwareInterfaces(bean, beanFactory, beanFactory); if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(context.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware && beanFactory != null) { StringValueResolver embeddedValueResolver = new EmbeddedValueResolver(beanFactory); ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(context); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(context); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(context); } if (APPLICATION_STARTUP_CLASS_PRESENT) { if (bean instanceof ApplicationStartupAware && applicationContext != null) { ((ApplicationStartupAware) bean).setApplicationStartup(applicationContext.getApplicationStartup()); } } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(context); } } /** * 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} */ 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 - 2024 Weber Informatics LLC | Privacy Policy