首页 > 作文

使用Springboot自定义注解,支持SPEL表达式

更新时间:2023-04-05 01:26:07 阅读: 评论:0

目录
springboot自定义注解,支持spel表达式1.自定义注解2.使用aop拦截方法,解析注解参数自定义注解结合切面和spel表达式自定义一个注解自定义一个rvice类,在需要拦截的方法上加上@log注解写一个自定义切面pom文件的依赖测试增加内容

springboot自定义注解,支持spel表达式

举例,自定义redis模糊删除注解

1.自定义注解

import java.lang.annota形容热的成语tion.elementtype;import java.lang.annotation.retention;import java.lang.annotation.retentionpolicy;import java.lang.annotation.target; @target(elementtype.method)@retention(retentionpolicy.runtime)public @interface cacheevictf委屈的近义词是什么uzzy {    /**     * redis key集合,模糊删除     * @return     */ 敬谢   string[] key() default ""; }

2.使用aop拦截方法,解析注解参数

import org.apache.commons.lang3.stringutils;import org.aspectj.lang.proceedingjoinpoint;import org.aspectj.lang.annotation.afterthrowing;import org.aspectj.lang.annotation.around;import org.aspectj.lang.annotation.aspect;import org.aspectj.lang.annotation.pointcut;import org.aspectj.lang.reflect.methodsignature;import org.slf4j.logger;import org.slf4j.loggerfactory;import org.springframework.beans.factory.annotation.autowired;import org.springframework.core.localvariabletableparameternamediscoverer;import org.springframework.core.annotation.order;import org.springframework.expression.expressionparr;import org.springframework.expression.spel.standard.spelexpressionparr;import org.springframework.expression.spel.support.standardevaluationcontext;import org.springframework.stereotype.component; import java.lang.reflect.method;import java.util.t;@aspect@order(1)@componentpublic class cachecleanfuzzyaspect {    logger logger = loggerfactory.getlogger(this.getclass());     @autowired    private redisutil redis;     //指定要执行aop的方法    @pointcut(value = "@annotation(cacheevictfuzzy)")    public void pointcut(cacheevictfuzzy cacheevictfuzzy){}      // 设置切面为加有 @rediscacheable注解的方法    @around("@annotation(cacheevictfuzzy)")    public object around(proceedingjoinpoint proceedingjoinpoint, cacheevictfuzzy cacheevictfuzzy){        return doredis(proceedingjoinpoint, cacheevictfuzzy);    }    @afterthrowing(pointcut = "@annotation(cacheevictfuzzy)", throwing = "error")    public void afterthrowing (throwable  error, cacheevictfuzzy cacheevictfuzzy){        logger.error(error.getmessage());    }     /**     * 删除缓存     * @param proceedingjoinpoint     * @param cacheevictfuzzy     * @return     */    private object doredis (proceedingjoinpoint proceedingjoinpoint, cacheevictfuzzy cacheevictfuzzy){        object result = null;        //得到被切面修饰的方法的参数列表        object[] args = proceedingjoinpoint.getargs();        // 得到被代理的方法        method method = ((methodsignature) proceedingjoinpoint.getsignature()).getmethod();        string[] keys = cacheevictfuzzy.key();        t<string> keyt = null;        string realkey = "";        for (int i = 0; i < keys.length; i++) {            if (stringutils.isblank(keys[i])){                continue;            }            realkey = parkey(keys[i], method, args);            keyt = redis.keys("*"+realkey+"*");            if (null != keyt && keyt.size()>0){                redis.delkeys(keyt);                logger.debug("拦截到方法:" + proceedingjoinpoint.getsignature().getname() + "方法");                logger.debug("删除的数据key为:"+keyt.tostring());            }        }        try {            result = proceedingjoinpoint.proceed();        } catch (throwable throwable) {            throwable.printstacktrace();        }finally {            return result;        }    }    /**     * 获取缓存的key     * key 定义在注解上,支持spel表达式     * @return     */    private string parkey(string key, method method, object [] args){         if(stringutils.impty(key)) return null;         //获取被拦截方法参数名列表(使用spring支持类库)        localvariabletableparameternamediscoverer u = new localvariabletableparameternamediscoverer();        string[] paranamearr = u.getparameternames(method);         //使用spel进行key的解析        expressionparr parr = new spelexpressionparr();        //spel上下文     三星s8什么时候上市   standardevaluationcontext context = new standardevaluationcontext();        //把方法参数放入spel上下文中        for(int i=0;i<paranamearr.length;i++){            context.tvariable(paranamearr[i], args[i]);        }        return parr.parexpression(key).getvalue(context,string.class);    }}

完事啦!

大家可以注意到关键方法就是parkey

    /**     * 获取缓存的key     * key 定义在注解上,支持spel表达式     * @return     */    private string parkey(string key, method method, object [] args){         if(stringutils.impty(key)) return null;         //获取被拦截方法参数名列表(使用spring支持类库)        localvariabletableparameternamediscoverer u = new localvariabletableparameternamediscoverer();        string[] paranamearr = u.ge祝老师端午节的祝福语tparameternames(method);         //使用spel进行key的解析        expressionparr parr = new spelexpressionparr();        //spel上下文        standardevaluationcontext context = new standardevaluationcontext();        //把方法参数放入spel上下文中        for(int i=0;i<paranamearr.length;i++){            context.tvariable(paranamearr[i], args[i]);        }        return parr.parexpression(key).getvalue(context,string.class);    }

自定义注解结合切面和spel表达式

在我们的实际开发中可能存在这么一种情况,当方法参数中的某些条件成立的时候,需要执行一些逻辑处理,比如输出日志。而这些代码可能都是差不多的,那么这个时候就可以结合自定义注解加上切面加上spel表达式进行处理。就比如在spring中我们可以使用@cacheable(key=”#xx”)实现缓存,这个#xx就是一个spel表达式。

需求:我们需要将rvice层方法中方法的某个参数的值大于0.5的方法,输出方法执行日志。(需要了解一些spel表达式的语法)

实现步骤:

1、自定义一个注解log

2、自定义一个切面,拦截所有方法上存在@log注解修饰的方法

3、写一个rvice层方法,方法上标注@log注解

难点:

在切面中需要拿到具体执行方法的方法名,可以使用spring提供的localvariabletableparameternamediscoverer来获取到

自定义一个注解

注意:注解中的spel的值是必须的,且spel表达式返回的结果应该是一个布尔值

/** * 记录日志信息,当spel表但是中的值为true时,输出日志信息 *  * @描述 * @作者 huan * @时间 2017年10月2日 - 上午10:25:39 */@target({ elementtype.method })@retention(retentionpolicy.runtime)public @interface log {string spel();string desc() default "描述";}

自定义一个rvice类,在需要拦截的方法上加上@log注解

写一个自定义切面

注意一下解析spel表达式中context的设值即可

/** * 日志切面,当条件满足时输出日志. *  * @描述 * @作者 huan * @时间 2017年10月2日 - 上午10:32:16 */@component@aspectpublic class logaspect {expressionparr parr = new spelexpressionparr();localvariabletableparameternamediscoverer discoverer = new localvariabletableparameternamediscoverer();@around("@annotation(log)")public object invoked(proceedingjoinpoint pjp, log log) throws throwable {object[] args = pjp.getargs();method method = ((methodsignature) pjp.getsignature()).getmethod();string spel = log.spel();string[] params = discoverer.getparameternames(method);evaluationcontext context = new standardevaluationcontext();for (int len = 0; len < params.length; len++) {context.tvariable(params[len], args[len]);}expression expression = parr.parexpression(spel);if (expression.getvalue(context, boolean.class)) {system.out.println(log.desc() + ",在" + new simpledateformat("yyyy-mm-dd hh:mm:ss").format(new date()) + "执行方法," + pjp.gettarget().getclass() + "." + method.getname()                         + "(" + convertargs(args) + ")");}return pjp.proceed();}private string convertargs(object[] args) {stringbuilder builder = new stringbuilder();for (object arg : args) {if (null == arg) {builder.append("null");} el {builder.append(arg.tostring());}builder.append(',');}builder.tcharat(builder.length() - 1, ' ');return builder.tostring();}}

pom文件的依赖

<parent><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-parent</artifactid><version>1.5.2.relea</version><relativepath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceencoding>utf-8</project.build.sourceencoding><project.reporting.outputencoding>utf-8</project.reporting.outputencoding><java.version>1.8</java.version></properties><dependencies><dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-aop</artifactid></dependency><dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-test</artifactid><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupid>org.springframework.boot</groupid><artifactid>spring-boot-maven-plugin</artifactid></plugin></plugins></build>

测试

增加内容

1、当我们想在自己写的spel表达式中调用spring bean 管理的方法时,如何写。spel表达式支持使用 @来引用bean,但是此时需要注入beanfactory

以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。

本文发布于:2023-04-05 01:26:05,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/1ba4d5c4e59868fa2fdc9106bfb8f52f.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:使用Springboot自定义注解,支持SPEL表达式.doc

本文 PDF 下载地址:使用Springboot自定义注解,支持SPEL表达式.pdf

标签:注解   方法   自定义   表达式
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图