本文是一个 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表达式的详细内容...