好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring组件开发模式支持SPEL表达式

本文是一个 spring 扩展支持 spel 的简单模式,方便第三方通过 spring 提供额外功能。

简化版方式

这种方式可以在任何能获取 applicationcontext 的地方使用。还可以提取一个方法处理动态 spel 表达式。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

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 的,下面是更推荐的一种用法。

推荐方式

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

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 注解 …

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接

原文链接:https://blog.csdn.net/isea533/article/details/84100428

查看更多关于Spring组件开发模式支持SPEL表达式的详细内容...

  阅读:18次