最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2018年12月24日 15:03:11   作者:isea533  
今天小編就為大家分享一篇關(guān)于Spring組件開發(fā)模式支持SPEL表達(dá)式,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧

本文是一個(gè) Spring 擴(kuò)展支持 SPEL 的簡(jiǎn)單模式,方便第三方通過 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 {
  /**
   * 通過 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í)際類型
        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í)際類型
    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 過濾方法
      return true;
    });
    return null;
  }
}

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

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

擴(kuò)展 Spring 我們必須了解這個(gè)順序,否則就沒法正確的使用各中對(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 方法
  • 自定義銷毀方法

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

靈活運(yùn)用

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

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

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

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

相關(guān)文章

  • Java如何根據(jù)根據(jù)IP地址獲取省市

    Java如何根據(jù)根據(jù)IP地址獲取省市

    這篇文章主要為大家詳細(xì)介紹了兩種在Java中獲取IP地址對(duì)應(yīng)地理位置信息的方法,分別是使用ip2region庫(kù)和GeoIP庫(kù),感興趣的小伙伴可以了解下
    2025-01-01
  • springboot讀取自定義配置文件節(jié)點(diǎn)的方法

    springboot讀取自定義配置文件節(jié)點(diǎn)的方法

    這篇文章主要介紹了springboot讀取自定義配置文件節(jié)點(diǎn)的方法,本文給大家介紹的非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2018-05-05
  • Java jar打包工具使用方法步驟解析

    Java jar打包工具使用方法步驟解析

    這篇文章主要介紹了Java jar打包工具使用方法步驟解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Springboot2以代碼的方式統(tǒng)一配置Jackson教程

    Springboot2以代碼的方式統(tǒng)一配置Jackson教程

    這篇文章主要介紹了Springboot2以代碼的方式統(tǒng)一配置Jackson教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 面試官:怎么做JDK8的垃圾收集器的調(diào)優(yōu)(面試常問)

    面試官:怎么做JDK8的垃圾收集器的調(diào)優(yōu)(面試常問)

    這篇文章主要介紹了面試官:怎么做JDK8的垃圾收集器的調(diào)優(yōu),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 詳解maven的setting配置文件中mirror和repository的區(qū)別

    詳解maven的setting配置文件中mirror和repository的區(qū)別

    這篇文章主要介紹了詳解maven的setting配置文件中mirror和repository的區(qū)別,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • SpringSecurity集成圖片驗(yàn)證碼的詳細(xì)過程

    SpringSecurity集成圖片驗(yàn)證碼的詳細(xì)過程

    SpringSecurity是通過過濾器鏈來完成的,接下來的驗(yàn)證碼,可以嘗試創(chuàng)建一個(gè)過濾器放到Security的過濾器鏈中,在自定義的過濾器中比較驗(yàn)證碼,本文通過實(shí)例代碼介紹SpringSecurity集成圖片驗(yàn)證碼的詳細(xì)過程,感興趣的朋友一起看看吧
    2023-12-12
  • SpringBoot部署到騰訊云的實(shí)現(xiàn)示例

    SpringBoot部署到騰訊云的實(shí)現(xiàn)示例

    記錄一下自己第一次部署springboot項(xiàng)目,本文主要介紹了SpringBoot部署到騰訊云的實(shí)現(xiàn)示例,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • tdesign的文件上傳功能實(shí)現(xiàn)(微信小程序+idea的springboot)

    tdesign的文件上傳功能實(shí)現(xiàn)(微信小程序+idea的springboot)

    這篇文章主要介紹了tdesign的文件上傳(微信小程序+idea的springboot)的相關(guān)知識(shí),本文通過圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-09-09
  • Java設(shè)計(jì)模式:組合模式

    Java設(shè)計(jì)模式:組合模式

    這篇文章主要介紹了快速理解Java設(shè)計(jì)模式中的組合模式,具有一定參考價(jià)值,需要的朋友可以了解下,希望能夠給你帶來幫助
    2021-09-09

最新評(píng)論

彰武县| 大方县| 公安县| 黄冈市| 蚌埠市| 广平县| 揭东县| 潜山县| 哈巴河县| 清原| 马关县| 上饶县| 天津市| 淮安市| 夹江县| 永靖县| 卫辉市| 定安县| 察雅县| 呼伦贝尔市| 柘荣县| 嘉黎县| 堆龙德庆县| 全椒县| 襄樊市| 谷城县| 舞阳县| 东源县| 湖北省| 湘乡市| 洛阳市| 泰宁县| 湖南省| 庄浪县| 哈巴河县| 武邑县| 顺平县| 秦皇岛市| 泰州市| 桦甸市| 奇台县|