content: package com.admin4j.spring.util;
  
  
  import com.admin4j.common.exception.Admin4jException;
  import lombok.Getter;
  import org.apache.commons.lang3.ObjectUtils;
  import org.springframework.aop.framework.AopContext;
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.NoSuchBeanDefinitionException;
  import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
  import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
  import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.ApplicationContextAware;
  import org.springframework.context.ConfigurableApplicationContext;
  
  /**
   * spring工具类 方便在非spring管理环境中获取bean
   *
   * @author andanyang
   */
  public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware {
  
      /**
       * Spring应用上下文环境
       */
      @Getter
      private static ApplicationContext applicationContext;
  
      /**
       * "@PostConstruct"注解标记的类中，由于ApplicationContext还未加载，导致空指针<br>
       * 因此实现BeanFactoryPostProcessor注入ConfigurableListableBeanFactory实现bean的操作
       */
      private static ConfigurableListableBeanFactory beanFactory;
  
      @Override
      public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
          SpringUtils.beanFactory = configurableListableBeanFactory;
      }
  
      @Override
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
          SpringUtils.applicationContext = applicationContext;
      }
  
      /**
       * 发布事件
       *
       * @param event
       */
      public static void publishEvent(Object event) {
          applicationContext.publishEvent(event);
      }
  
      /**
       * 获取对象
       *
       * @param name
       * @return Object 一个以所给名字注册的bean的实例
       * @throws BeansException
       */
      @SuppressWarnings("unchecked")
      public static <T> T getBean(String name) throws BeansException {
          return (T) applicationContext.getBean(name);
      }
  
      /**
       * 获取类型为requiredType的对象
       *
       * @param clz
       * @return
       * @throws BeansException
       */
      public static <T> T getBean(Class<T> clz) throws BeansException {
          return applicationContext.getBean(clz);
      }
  
      /**
       * 如果beanFactory包含一个与所给名称匹配的bean定义，则返回true
       *
       * @param name
       * @return boolean
       */
      public static boolean containsBean(String name) {
          return applicationContext.containsBean(name);
      }
  
      /**
       * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到，将会抛出一个异常（NoSuchBeanDefinitionException）
       *
       * @param name
       * @return boolean
       * @throws NoSuchBeanDefinitionException
       */
      public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
          return applicationContext.isSingleton(name);
      }
  
      /**
       * @param name
       * @return Class 注册对象的类型
       * @throws NoSuchBeanDefinitionException
       */
      public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
          return applicationContext.getType(name);
      }
  
      /**
       * 如果给定的bean名字在bean定义中有别名，则返回这些别名
       *
       * @param name
       * @return
       * @throws NoSuchBeanDefinitionException
       */
      public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
          return applicationContext.getAliases(name);
      }
  
      /**
       * 获取aop代理对象
       *
       * @param invoker
       * @return
       */
      @SuppressWarnings("unchecked")
      public static <T> T getAopProxy(T invoker) {
          return (T) AopContext.currentProxy();
      }
  
      /**
       * 获取{@link ConfigurableListableBeanFactory}
       *
       * @return {@link ConfigurableListableBeanFactory}
       * @throws Admin4jException 当上下文非ConfigurableListableBeanFactory抛出异常
       * @since 5.7.7
       */
      public static ConfigurableListableBeanFactory getConfigurableBeanFactory() {
          final ConfigurableListableBeanFactory factory;
          if (null != beanFactory) {
              factory = beanFactory;
          } else if (applicationContext instanceof ConfigurableApplicationContext) {
              factory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
          } else {
              throw new Admin4jException("No ConfigurableListableBeanFactory from context!");
          }
          return factory;
      }
  
      /**
       * 获取配置文件配置项的值
       *
       * @param key 配置项key
       * @return 属性值
       */
      public static String getProperty(String key) {
          if (null == applicationContext) {
              return null;
          }
          return applicationContext.getEnvironment().getProperty(key);
      }
  
      public static String getProperty(String key, String defaultValue) {
          if (null == applicationContext) {
              return null;
          }
          return applicationContext.getEnvironment().getProperty(key, defaultValue);
      }
  
      /**
       * 获取应用程序名称
       *
       * @return 应用程序名称
       */
      public static String getApplicationName() {
          return getProperty("spring.application.name");
      }
  
      /**
       * 获取当前的环境配置，无配置返回null
       *
       * @return 当前的环境配置
       */
      public static String[] getActiveProfiles() {
          if (null == applicationContext) {
              return null;
          }
          return applicationContext.getEnvironment().getActiveProfiles();
      }
  
      /**
       * 获取当前的环境配置，当有多个环境配置时，只获取第一个
       *
       * @return 当前的环境配置
       */
      public static String getActiveProfile() {
          final String[] activeProfiles = getActiveProfiles();
          return ObjectUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
      }
  
      /**
       * 动态向Spring注册Bean
       * <p>
       * 由{@link org.springframework.beans.factory.BeanFactory} 实现，通过工具开放API
       * <p>
       *
       * @param <T>      Bean类型
       * @param beanName 名称
       * @param bean     bean
       */
      public static <T> void registerBean(String beanName, T bean) {
          final ConfigurableListableBeanFactory factory = getConfigurableBeanFactory();
          factory.autowireBean(bean);
          factory.registerSingleton(beanName, bean);
      }
  
      /**
       * 注销bean
       * <p>
       * 将Spring中的bean注销，请谨慎使用
       *
       * @param beanName bean名称
       */
      public static void unregisterBean(String beanName) {
          final ConfigurableListableBeanFactory factory = getConfigurableBeanFactory();
          if (factory instanceof DefaultSingletonBeanRegistry) {
              DefaultSingletonBeanRegistry registry = (DefaultSingletonBeanRegistry) factory;
              registry.destroySingleton(beanName);
          } else {
              throw new Admin4jException("Can not unregister bean, the factory is not a DefaultSingletonBeanRegistry!");
          }
      }
  }
  