AOP 实现自定义注解
1.自定义注解
2.编写 AOP
3.测试
1.自定义注解
package com.base.yun.spring.aop; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 说明: * 定义日志注解 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FileLog { String value() default "记录日志"; }
2.编写 AOP
package com.base.yun.spring.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /** * 说明: 日志的切面处理程序 */ @Aspect @Component public class LogAspect { @Before("within(com.base.yun.spring.service.*) && @annotation(fileLog)") public void doAccessCheck(JoinPoint jp, FileLog fileLog) { System.out.println("前置通知-->>"); } @After("within(com.base.yun.spring.service.*) && @annotation(fileLog)") public void doAfterReturning(JoinPoint jp, FileLog fileLog) { System.out.println("后置通知-->>"); } @Around("within(com.base.yun.spring.service.*) && @annotation(fileLog)") public Object doAround(ProceedingJoinPoint pJoinPoint, FileLog fileLog) throws Throwable { System.out.println("环绕通知开始"); // 这里如果pJoinPoint.proceed()不执行,后面拦截到的方法都不会执行,非常适用于权限管理 Object result = pJoinPoint.proceed(); System.out.println("环绕通知结束"); return result; } @AfterReturning("within(com.base.yun.spring.service.*) && @annotation(fileLog)") public void addSuccessLog(JoinPoint jp, FileLog fileLog) { Object[] parames = jp.getArgs(); // 获取目标方法体参数 String className = jp.getTarget().getClass().toString(); // 获取目标类名 String signature = jp.getSignature().toString(); // 获取目标方法签名 String methodName = signature.substring(signature.lastIndexOf(".") + 1, signature.indexOf("(")); // 获取注解值 String desc = fileLog.value(); // 把调用的信息写到日常记录信息里面去... System.out.println("最终通知注解值:"+desc); } // 标注该方法体为异常通知,当目标方法出现异常时,执行该方法体 @AfterThrowing(pointcut = "within(com.base.yun.spring.service.*) && @annotation(fileLog)", throwing = "e") public void addExceptionLog(JoinPoint jp, FileLog fileLog, Exception e) { System.out.println("异常通知-->"); // 把错误信息写到错误日志文件里面去... } }
3.测试
<aop:aspectj-autoproxy/> <bean class="com.base.yun.spring.aop.LogAspect"/> <bean id="purchaseService" class="com.base.yun.spring.service.PurchaseService" />
package spring; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.base.yun.spring.service.PurchaseService; public class AopTest { @Test public void testAop() { ApplicationContext ctx = new ClassPathXmlApplicationContext("user.xml"); PurchaseService service = ctx.getBean("purchaseService",PurchaseService.class); service.purchaseProduct("电风扇", 98, "日用品"); } }
测试结果:
环绕通知开始 前置通知-->> 购买商品。。。 环绕通知结束 后置通知-->> 最终通知注解值:记录日志