利用spring AOP记录用户操作日志的方法示例
程序员文章站
2023-12-11 08:28:46
前言
最近项目已经开发完成,但发现需要加用户操作日志,如果返回去加也不太现实,所以使用springaop来完成比较合适。下面来一起看看详细的介绍:
注解工具类:...
前言
最近项目已经开发完成,但发现需要加用户操作日志,如果返回去加也不太现实,所以使用springaop来完成比较合适。下面来一起看看详细的介绍:
注解工具类:
@retention(retentionpolicy.runtime) @target(elementtype.method) public @interface logannotation { string operatemodelnm() default ""; string operatefuncnm() default ""; string operatedescribe() default ""; }
切面类:
@aspect public class myinterceptor { @pointcut("execution(** com.luchao.spring.test3.service.impl.*.*(..))") private void anymethod(){}//定义一个切入点 @before("anymethod() && args(name)") public void doaccesscheck(string name){ system.out.println(name); system.out.println("前置通知"); } @afterreturning("anymethod()") public void doafter(){ system.out.println("后置通知"); } @after("anymethod()") public void after(joinpoint point){ system.out.println("最终通知"); } @afterthrowing("anymethod()") public void doafterthrow(){ system.out.println("例外通知"); } @around("anymethod()") public object dobasicprofiling(proceedingjoinpoint pjp) throws throwable{ signature signature = pjp.getsignature(); methodsignature methodsignature = (methodsignature)signature; method targetmethod = methodsignature.getmethod(); // system.out.println("classname:" + targetmethod.getdeclaringclass().getname()); // system.out.println("superclass:" + targetmethod.getdeclaringclass().getsuperclass().getname()); // system.out.println("isinterface:" + targetmethod.getdeclaringclass().isinterface()); // system.out.println("target:" + pjp.gettarget().getclass().getname()); // system.out.println("proxy:" + pjp.getthis().getclass().getname()); // system.out.println("method:" + targetmethod.getname()); class[] parametertypes = new class[pjp.getargs().length]; object[] args = pjp.getargs(); for(int i=0; i<args.length; i++) { if(args[i] != null) { parametertypes[i] = args[i].getclass(); }else { parametertypes[i] = null; } } //获取代理方法对象 string methodname = pjp.getsignature().getname(); method method = pjp.getsignature().getdeclaringtype().getmethod(methodname, parametertypes); if(method.isannotationpresent(logannotation.class)){ system.out.println("存在1"); } //获取实际方法对象,可以获取方法注解等 method realmethod = pjp.gettarget().getclass().getdeclaredmethod(signature.getname(), targetmethod.getparametertypes()); if(realmethod.isannotationpresent(logannotation.class)){ realmethod.getannotation(logannotation.class).operatedescribe(); system.out.println("存在2"); } system.out.println("进入环绕通知"); object object = pjp.proceed();//执行该方法 system.out.println("退出方法"); return object; } }
配置类:
@configurable @enableaspectjautoproxy @componentscan(basepackages = "com.luchao.spring.test3") public class test3config { @bean public myinterceptor myinterceptor(){ return new myinterceptor(); } @bean public encoreableintroducer encoreableintroducer(){ return new encoreableintroducer(); } }
服务类:
@component public class personservicebean implements personserver { /** * 保存方法 * @param name */ @logannotation(operatemodelnm = "测试方法", operatefuncnm = "保存方法") public void save(string name) { system.out.println("我是save方法"); } /** * 更新方法 * @param name * @param id */ public void update(string name, integer id) { system.out.println("我是update()方法"); } /** * 获取方法 * @param id * @return */ public string getpersonname(integer id) { system.out.println("我是getpersonname()方法"); return "xxx"; } }
测试方法:
@runwith(springjunit4classrunner.class) @contextconfiguration(classes = test3config.class) public class springaoptest { @autowired private personserver personserver; @test public void inteceptortest(){ encoreable encoreable = (encoreable)personserver; encoreable.performencore(); personserver.save("test"); } }
在springaop切面中使用的是代理,所以直接获取的是代理对象,不能获取真实对象的一些信息,如注解等。
//获取代理方法对象 string methodname = pjp.getsignature().getname(); method method = pjp.getsignature().getdeclaringtype().getmethod(methodname, parametertypes);
如果要获取真实对象,获取注解的信息,可以方便我们进行判断记录。
//获取实际方法对象,可以获取方法注解等 method realmethod = pjp.gettarget().getclass().getdeclaredmethod(signature.getname(), targetmethod.getparametertypes());
这样就完成了一个简单的操作日志记录demo。另外,如果不是讲某个方法设置切点,可以ant风格的切点切入方式,设置多个或所有方法。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。