麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 開(kāi)發(fā) > Java > 正文

Spring組件開(kāi)發(fā)模式支持SPEL表達(dá)式

2024-07-14 08:43:19
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文是一個(gè) Spring 擴(kuò)展支持 SPEL 的簡(jiǎn)單模式,方便第三方通過(guò) Spring 提供額外功能。

簡(jiǎn)化版方式

這種方式可以在任何能獲取ApplicationContext 的地方使用。還可以提取一個(gè)方法處理動(dòng)態(tài) SPEL 表達(dá)式。

import org.springframework.aop.support.AopUtils;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.*;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.expression.StandardBeanExpressionResolver;import org.springframework.core.annotation.AnnotationUtils;import java.lang.reflect.Method;/** * 針對(duì) Spring 實(shí)現(xiàn)某些特殊邏輯時(shí),支持 SPEL 表達(dá)式 * @author liuzh */public class SpelUtil implements ApplicationContextAware {  /**   * 通過(guò) ApplicationContext 處理時(shí)   * @param applicationContext   * @throws BeansException   */  @Override  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {    if (applicationContext instanceof ConfigurableApplicationContext) {      ConfigurableApplicationContext context = (ConfigurableApplicationContext)applicationContext;      ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();      StandardBeanExpressionResolver expressionResolver = new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader());      for (String definitionName : applicationContext.getBeanDefinitionNames()) {        BeanDefinition definition = beanFactory.getBeanDefinition(definitionName);        Scope scope = (definition != null ? beanFactory.getRegisteredScope(definition.getScope()) : null);        //根據(jù)自己邏輯處理        //例如獲取 bean        Object bean = applicationContext.getBean(definitionName);        //獲取實(shí)際類(lèi)型        Class<?> targetClass = AopUtils.getTargetClass(bean);        //獲取所有方法        for (Method method : targetClass.getDeclaredMethods()) {          //獲取自定義的注解(Bean是個(gè)例子)          Bean annotation = AnnotationUtils.findAnnotation(method, Bean.class);          //假設(shè)下面的 value 支持 SPEL          for (String val : annotation.value()) {            //解析 ${} 方式的值            val = beanFactory.resolveEmbeddedValue(val);            //解析 SPEL 表達(dá)式            Object value = expressionResolver.evaluate(val, new BeanExpressionContext(beanFactory, scope));            //TODO 其他邏輯          }        }      }    }  }}

上面是完全針對(duì)ApplicationContext的,下面是更推薦的一種用法。

推薦方式

import org.springframework.aop.support.AopUtils;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanClassLoaderAware;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.config.*;import org.springframework.context.annotation.Bean;import org.springframework.context.expression.StandardBeanExpressionResolver;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.util.ReflectionUtils;/** * 針對(duì) Spring 實(shí)現(xiàn)某些特殊邏輯時(shí),支持 SPEL 表達(dá)式 * @author liuzh */public class SpelUtil2 implements BeanPostProcessor, BeanFactoryAware, BeanClassLoaderAware {  private BeanFactory beanFactory;  private BeanExpressionResolver resolver;  private BeanExpressionContext expressionContext;  /**   * 解析 SPEL   * @param value   * @return   */  private Object resolveExpression(String value){    String resolvedValue = resolve(value);    if (!(resolvedValue.startsWith("#{") && value.endsWith("}"))) {      return resolvedValue;    }    return this.resolver.evaluate(resolvedValue, this.expressionContext);  }  /**   * 解析 ${}   * @param value   * @return   */  private String resolve(String value){    if (this.beanFactory != null && this.beanFactory instanceof ConfigurableBeanFactory) {      return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value);    }    return value;  }  @Override  public void setBeanClassLoader(ClassLoader classLoader) {    this.resolver = new StandardBeanExpressionResolver(classLoader);  }  @Override  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {    this.beanFactory = beanFactory;    if(beanFactory instanceof ConfigurableListableBeanFactory){      this.resolver = ((ConfigurableListableBeanFactory) beanFactory).getBeanExpressionResolver();      this.expressionContext = new BeanExpressionContext((ConfigurableListableBeanFactory) beanFactory, null);    }  }  @Override  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    return bean;  }  /**   * 對(duì) bean 的后置處理   * @param bean   * @param beanName   * @return   * @throws BeansException   */  @Override  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {    //獲取實(shí)際類(lèi)型    Class<?> targetClass = AopUtils.getTargetClass(bean);    //獲取所有方法    ReflectionUtils.doWithMethods(targetClass, method -> {      //獲取自定義的注解(Bean是個(gè)例子)      Bean annotation = AnnotationUtils.findAnnotation(method, Bean.class);      //假設(shè)下面的 value 支持 SPEL      for (String val : annotation.value()) {        //解析表達(dá)式        Object value = resolveExpression(val);        //TODO 其他邏輯      }    }, method -> {      //TODO 過(guò)濾方法      return true;    });    return null;  }}

這種方式利用了 Spring 生命周期的幾個(gè)接口來(lái)獲取需要用到的對(duì)象。

Spring 生命周期調(diào)用順序

擴(kuò)展 Spring 我們必須了解這個(gè)順序,否則就沒(méi)法正確的使用各中對(duì)象。

完整的初始化方法及其標(biāo)準(zhǔn)順序是:

  • BeanNameAware 的 setBeanName 方法
  • BeanClassLoaderAware 的 setBeanClassLoader 方法
  • BeanFactoryAware 的 setBeanFactory 方法
  • EnvironmentAware 的 setEnvironment 方法
  • EmbeddedValueResolverAware 的 setEmbeddedValueResolver 方法
  • ResourceLoaderAware 的 setResourceLoader 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
  • ApplicationEventPublisherAware 的 setApplicationEventPublisher 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
  • MessageSourceAware 的 setMessageSource 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
  • ApplicationContextAware 的 setApplicationContext 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
  • ServletContextAware 的 setServletContext 方法 (僅在Web應(yīng)用程序上下文中運(yùn)行時(shí)適用)
  • BeanPostProcessors 的 postProcessBeforeInitialization 方法
  • InitializingBean 的 afterPropertiesSet 方法
  • 自定義初始化方法
  • BeanPostProcessors 的 postProcessAfterInitialization 方法

關(guān)閉bean工廠時(shí),以下生命周期方法適用:

  • DestructionAwareBeanPostProcessors 的 postProcessBeforeDestruction 方法
  • DisposableBean 的 destroy 方法
  • 自定義銷(xiāo)毀方法

參考:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html

靈活運(yùn)用

利用上述模式可以實(shí)現(xiàn)很多便捷的操作。

Spring 中,使用類(lèi)似模式的地方有:

  • @Value 注解支持 SPEL(和 ${})
  • @Cache 相關(guān)的注解(支持 SPEL)
  • @EventListener 注解
  • @RabbitListener 注解

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)VeVb武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JAVA教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产一级一国产一级毛片 | www日韩在线观看 | 91天堂国产在线 | 色999国产| 99视频在线观看视频 | 一区二区久久久久草草 | 久久久资源网 | 中文字幕涩涩久久乱小说 | 91久久久久久 | 免费亚洲视频在线观看 | 斗破苍穹在线观看免费完整观看 | 欧美国产精品久久 | 久草视频在线资源 | 九九热在线视频观看 | 欧美成人免费香蕉 | 九色激情网 | 中国hdxxxx护士爽在线观看 | 双性精h调教灌尿打屁股的文案 | 国产视频精品在线 | 欧美成人精品一区二区三区 | av噜噜在线 | 青青草在线免费观看 | 国产免费高清在线视频 | 免费黄色短视频网站 | 欧美日韩在线播放 | 在线男人天堂 | h视频免费观看 | 日韩激情在线视频 | 欧美乱论| 99麻豆久久久国产精品免费 | 九九午夜 | 欧美大电影免费观看 | 激情宗合 | 永久av在线免费观看 | 日韩视频一区二区三区在线观看 | 欧美精品成人一区二区在线观看 | 色播视频网站 | 高清av免费 | 国产成人精品日本亚洲语音 | 亚洲一区二区三区日本久久九 | 欧美成人一级片 |