亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Spring組件開發模式支持SPEL表達式

2024-07-14 08:43:19
字體:
來源:轉載
供稿:網友

本文是一個 Spring 擴展支持 SPEL 的簡單模式,方便第三方通過 Spring 提供額外功能。

簡化版方式

這種方式可以在任何能獲取ApplicationContext 的地方使用。還可以提取一個方法處理動態 SPEL 表達式。

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;/** * 針對 Spring 實現某些特殊邏輯時,支持 SPEL 表達式 * @author liuzh */public class SpelUtil implements ApplicationContextAware {  /**   * 通過 ApplicationContext 處理時   * @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);        //根據自己邏輯處理        //例如獲取 bean        Object bean = applicationContext.getBean(definitionName);        //獲取實際類型        Class<?> targetClass = AopUtils.getTargetClass(bean);        //獲取所有方法        for (Method method : targetClass.getDeclaredMethods()) {          //獲取自定義的注解(Bean是個例子)          Bean annotation = AnnotationUtils.findAnnotation(method, Bean.class);          //假設下面的 value 支持 SPEL          for (String val : annotation.value()) {            //解析 ${} 方式的值            val = beanFactory.resolveEmbeddedValue(val);            //解析 SPEL 表達式            Object value = expressionResolver.evaluate(val, new BeanExpressionContext(beanFactory, scope));            //TODO 其他邏輯          }        }      }    }  }}

上面是完全針對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;/** * 針對 Spring 實現某些特殊邏輯時,支持 SPEL 表達式 * @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;  }  /**   * 對 bean 的后置處理   * @param bean   * @param beanName   * @return   * @throws BeansException   */  @Override  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {    //獲取實際類型    Class<?> targetClass = AopUtils.getTargetClass(bean);    //獲取所有方法    ReflectionUtils.doWithMethods(targetClass, method -> {      //獲取自定義的注解(Bean是個例子)      Bean annotation = AnnotationUtils.findAnnotation(method, Bean.class);      //假設下面的 value 支持 SPEL      for (String val : annotation.value()) {        //解析表達式        Object value = resolveExpression(val);        //TODO 其他邏輯      }    }, method -> {      //TODO 過濾方法      return true;    });    return null;  }}

這種方式利用了 Spring 生命周期的幾個接口來獲取需要用到的對象。

Spring 生命周期調用順序

擴展 Spring 我們必須了解這個順序,否則就沒法正確的使用各中對象。

完整的初始化方法及其標準順序是:

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

關閉bean工廠時,以下生命周期方法適用:

  • DestructionAwareBeanPostProcessors 的 postProcessBeforeDestruction 方法
  • DisposableBean 的 destroy 方法
  • 自定義銷毀方法

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

靈活運用

利用上述模式可以實現很多便捷的操作。

Spring 中,使用類似模式的地方有:

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美精品一区| 成人国产在线视频| 裸体女人亚洲精品一区| 日韩一区在线视频| 日韩小视频网址| 久久精品久久久久久国产 免费| 国产69久久精品成人看| 欧美最近摘花xxxx摘花| 国产日产欧美a一级在线| 在线丨暗呦小u女国产精品| 日韩午夜在线视频| 国产成人精品久久亚洲高清不卡| 7m第一福利500精品视频| 亚洲一区二区精品| 色妞久久福利网| 国产精品亚洲片夜色在线| 亚洲视频在线观看视频| 性色av一区二区三区| 激情成人在线视频| 日韩在线国产精品| 欧美色图在线视频| 粉嫩av一区二区三区免费野| 国产精品美女在线| 欧美体内谢she精2性欧美| 亚洲精美色品网站| 欧美成人精品在线观看| 国产欧美精品va在线观看| 日韩高清电影好看的电视剧电影| 成人亲热视频网站| 一本大道亚洲视频| 亚洲肉体裸体xxxx137| 亚洲精品国产成人| 欧美一区在线直播| 欧美精品激情在线观看| 国模视频一区二区三区| 日韩最新av在线| 69国产精品成人在线播放| 在线观看中文字幕亚洲| 国内精品中文字幕| 欧美精品videosex牲欧美| 成人免费福利视频| 久久亚洲精品国产亚洲老地址| 亚洲第一国产精品| 亚洲成人精品av| 国产精品久久久久久久久久久新郎| www.日韩视频| 国产精品久久久久久久9999| 日本久久久a级免费| 青青在线视频一区二区三区| 66m—66摸成人免费视频| www国产91| 97涩涩爰在线观看亚洲| 国产一级揄自揄精品视频| 久久九九热免费视频| 久久频这里精品99香蕉| 最近2019中文字幕第三页视频| 亚洲成人激情在线| 亚洲女成人图区| 亚洲精品久久久久久久久久久久久| 国产精品成久久久久三级| www.亚洲人.com| 中文字幕欧美精品日韩中文字幕| 国产精品福利无圣光在线一区| 欧美激情精品久久久| 亚洲欧洲一区二区三区在线观看| 国产美女被下药99| 亚洲精品久久久久久久久久久久| 亚洲国产欧美一区二区丝袜黑人| 在线观看91久久久久久| 亚洲美女在线看| 精品香蕉一区二区三区| 亚洲自拍av在线| 青青草99啪国产免费| 午夜欧美不卡精品aaaaa| 亚洲自拍小视频| 亚洲国产成人爱av在线播放| 欧美激情视频在线免费观看 欧美视频免费一| 亚洲精品视频播放| 亚洲人成在线电影| 蜜臀久久99精品久久久无需会员| 久久久久久久久久久网站| 久久精品亚洲国产| 91久久国产婷婷一区二区| 91极品视频在线| 国产福利成人在线| 亚洲国产美女精品久久久久∴| 久久国产精品电影| 国产香蕉精品视频一区二区三区| 91av视频导航| 91精品国产91久久久久久最新| 欧美在线观看网站| 亚洲人线精品午夜| 最近2019中文字幕一页二页| 国产精品美女呻吟| 亚洲欧美变态国产另类| 日韩精品在线观看一区二区| 亚洲激情视频网| 91精品啪在线观看麻豆免费| 精品色蜜蜜精品视频在线观看| 麻豆国产va免费精品高清在线| 国产精品久久久久影院日本| 亚洲精品自产拍| 国产综合久久久久久| 国产免费亚洲高清| 国产91色在线| 欧美国产日韩一区二区| 青青青国产精品一区二区| 久久久久久这里只有精品| 亚洲一区二区中文字幕| 日韩在线观看电影| 亚洲第一av网站| 成人激情视频在线| 成人h片在线播放免费网站| 上原亚衣av一区二区三区| 国产91色在线播放| 97精品久久久中文字幕免费| 亚洲精品久久久久中文字幕欢迎你| 亚洲国产欧美日韩精品| 日韩激情av在线免费观看| 亚洲摸下面视频| 性欧美暴力猛交69hd| 亚洲欧洲日本专区| 久久国产色av| 国产精品尤物福利片在线观看| 97精品国产91久久久久久| 亚洲天堂av高清| 欧美性猛交xxx| 日韩一级裸体免费视频| 欧美高清激情视频| 一区二区三区四区精品| 97热精品视频官网| 精品小视频在线| 欧美日韩一区二区三区在线免费观看| 91亚洲va在线va天堂va国| 国产成人福利夜色影视| 久久综合免费视频| 亚洲国产成人在线视频| 色综合色综合久久综合频道88| 久久久久久久久网站| 黑人巨大精品欧美一区二区| 久久久精品国产亚洲| 久久久久久久久91| 国产精品中文字幕在线| 不卡av在线播放| 欧美精品videosex性欧美| 久久综合久久美利坚合众国| 揄拍成人国产精品视频| 日韩欧美国产中文字幕| 91久久夜色精品国产网站| 日本一欧美一欧美一亚洲视频| 亚洲aⅴ男人的天堂在线观看| 久久99精品久久久久久青青91| 久久久久久久久综合| 久久男人的天堂| 蜜臀久久99精品久久久久久宅男| 亚洲欧美综合精品久久成人| 欧美大尺度在线观看| 国产一区二区三区毛片| 91成人天堂久久成人| 色久欧美在线视频观看| 欧洲精品久久久| 伊人久久男人天堂| 亚洲人成网站在线播| 亚洲国产欧美在线成人app|