利用spring AOP記錄用戶(hù)操作日志的方法示例
前言
最近項(xiàng)目已經(jīng)開(kāi)發(fā)完成,但發(fā)現(xiàn)需要加用戶(hù)操作日志,如果返回去加也不太現(xiàn)實(shí),所以使用springAOP來(lái)完成比較合適。下面來(lái)一起看看詳細(xì)的介紹:
注解工具類(lèi):
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogAnnotation { String operateModelNm() default ""; String operateFuncNm() default ""; String operateDescribe() default ""; }
切面類(lèi):
@Aspect public class MyInterceptor { @Pointcut("execution(** com.luchao.spring.test3.service.impl.*.*(..))") private void anyMethod(){}//定義一個(gè)切入點(diǎn) @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; } } //獲取代理方法對(duì)象 String methodName = pjp.getSignature().getName(); Method method = pjp.getSignature().getDeclaringType().getMethod(methodName, parameterTypes); if(method.isAnnotationPresent(LogAnnotation.class)){ System.out.println("存在1"); } //獲取實(shí)際方法對(duì)象,可以獲取方法注解等 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("進(jìn)入環(huán)繞通知"); Object object = pjp.proceed();//執(zhí)行該方法 System.out.println("退出方法"); return object; } }
配置類(lèi):
@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(); } }
服務(wù)類(lèi):
@Component public class PersonServiceBean implements PersonServer { /** * 保存方法 * @param name */ @LogAnnotation(operateModelNm = "測(cè)試方法", 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"; } }
測(cè)試方法:
@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切面中使用的是代理,所以直接獲取的是代理對(duì)象,不能獲取真實(shí)對(duì)象的一些信息,如注解等。
//獲取代理方法對(duì)象 String methodName = pjp.getSignature().getName(); Method method = pjp.getSignature().getDeclaringType().getMethod(methodName, parameterTypes);
如果要獲取真實(shí)對(duì)象,獲取注解的信息,可以方便我們進(jìn)行判斷記錄。
//獲取實(shí)際方法對(duì)象,可以獲取方法注解等 Method realMethod = pjp.getTarget().getClass().getDeclaredMethod(signature.getName(), targetMethod.getParameterTypes());
這樣就完成了一個(gè)簡(jiǎn)單的操作日志記錄demo。另外,如果不是講某個(gè)方法設(shè)置切點(diǎn),可以ant風(fēng)格的切點(diǎn)切入方式,設(shè)置多個(gè)或所有方法。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
spring boot項(xiàng)目打包成war在tomcat運(yùn)行的全步驟
這篇文章主要給大家介紹了關(guān)于spring boot項(xiàng)目打包成war在tomcat運(yùn)行的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Java框架篇:Spring+SpringMVC+hibernate整合開(kāi)發(fā)
本篇文章將會(huì)對(duì)Spring+SpringMVC+hibernate的整合開(kāi)發(fā)進(jìn)行介紹。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-02-02Spring Cloud Stream分區(qū)分組原理圖解
這篇文章主要介紹了Spring Cloud Stream的分區(qū)和分組,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03解決springboot的findOne方法沒(méi)有合適的參數(shù)使用問(wèn)題
這篇文章主要介紹了解決springboot的findOne方法沒(méi)有合適的參數(shù)使用問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java網(wǎng)絡(luò)編程教程之設(shè)置請(qǐng)求超時(shí)的方法
這篇文章主要給大家介紹了關(guān)于Java網(wǎng)絡(luò)編程教程之設(shè)置請(qǐng)求超時(shí)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12