常用工具类Aop的使用

AOP思想:

AOP(Aspect Oriented Programming)是一种面向切面的编程思想。面向切面编程是将程序抽象成各个切面,即解剖对象的内部,将那些影响了多个类的公共行为抽取到一个可重用模块里,减少系统的重复代码,降低模块间的耦合度,增强代码的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理、增强处理。

AOP的使用场景:

权限认证、日志、事务处理、增强处理

 正常导入Aspect依赖包、 maven库可以找到Aspect相关的依赖

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

相关注解介绍

@Aspect:作用是把当前类标识为一个切面供容器读取
 
@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行

@Aspect的使用以及基本概念:
1.切面类 @Aspect: 定义切面类,加上@Aspect、@Component注解

@Aspect
@Component
//设置注解执行的顺序
@Order(2)
public class AnnotationAspectTest 

2.切点 @Pointcut

    /**
     * 定义切点,切点为对应controller
     */
    @Pointcut("execution(public * com.example.zcs.Aop.controller.*.*(..))")
    public void aopPointCut(){
 
    }

注:execution表达式第一个*表示匹配任意的方法返回值,第二个*表示所有controller包下的类,第三个*表示所有方法,第一个..表示任意参数个数。
3.Advice,在切入点上执行的增强处理,主要有五个注解:

    @Before  在切点方法之前执行

       @After  在切点方法之后执行

       @AfterReturning 切点方法返回后执行

     @AfterThrowing 切点方法抛异常执行

     @Around 属于环绕增强,能控制切点执行前,执行后

4.JoinPoint :方法中的参数JoinPoint为连接点对象,它可以获取当前切入的方法的参数、代理类等信息,因此可以记录一些信息,验证一些信息等;

5.使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系;

6.@annotation(annotationType) 匹配指定注解为切入点的方法;

具体代码实现:
1.AopController,用于校验aop是否生效:

@Controller
@RequestMapping("aop")
public class AopController {
 
    @RequestMapping("test")
    @ResponseBody
    public String aopTest(User user) {
       // System.out.println(user);
        System.out.println("aop测试");
        return "success";
 
    }
 
    @TestAnnotation(flag = false)
    @RequestMapping("aopAnnotationTest")
    @ResponseBody
    public String aopAnnotationTest(User user) {
        // System.out.println(user);
        System.out.println("aopAnnotationTest");
        return "success";
 
    }
 
}

2.AspectTest,具体的切面类,用于添加横切逻辑,切点使用execution表达式进行匹配

@Aspect
@Component
//设置注解执行的顺序
@Order(1)
public class AspectTest {
 
    /**
     * 定义切点,切点为对应controller
     */
    @Pointcut("execution(public * com.example.zcs.Aop.controller.*.*(..))")
    public void aopPointCut(){
 
    }
 
    @Before("aopPointCut()")
    public void testbefor(JoinPoint joinPoint) {
        illegalParam(joinPoint);
        System.out.println("执行方法之前执行。。。。。");
    }
    
 
    @After("aopPointCut()")
    public void testAfter(JoinPoint joinPoint) {
        //illegalParam(joinPoint);
        System.out.println("执行方法之后执行。。。。。");
    }
 
    /**
     *获取请求参数
     * @param joinPoint
     * @return
     */
    private static void  illegalParam(JoinPoint joinPoint) {
        if(joinPoint == null){
            return;
        }
        boolean flag = false;
        try{
            // 参数值
            Object[] args = joinPoint.getArgs();
            if (args != null) {
                for (Object o : args) {
                    System.out.println(o);
 
                }
            }
        }catch(Exception e){
        }
    }
    
}

3.AnnotationAspectTest类,具体的切面类,用于添加横切逻辑,切点指定注解

@Aspect
@Component
//设置注解执行的顺序
@Order(2)
public class AnnotationAspectTest {
    /**
     * 定义切点,切点为添加了注解的方法
     */
    @Pointcut("@annotation(com.example.zcs.Aop.annotation.TestAnnotation)")
    public void aopPointCut(){
    }
 
    @Around("aopPointCut()")
    public Object Around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("AnnotationAspectTest Around start ");
        //获取注解和注解的值
        TestAnnotation annotation = getAnnotation(point);
       if (annotation != null) {
           boolean flag = annotation.flag();
           System.out.println("注解flags的值:" + flag);
       }
 
        //获取参数
        Object[] args = point.getArgs();
 
        for (Object arg : args) {
            System.out.println("arg ==>" + arg);
        }
 
        //去调用被拦截的方法
        Object proceed = point.proceed();
 
        return proceed;
    }
 
    //获取注解
    public TestAnnotation getAnnotation(ProceedingJoinPoint point) {
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null){
            return method.getAnnotation(TestAnnotation.class);
        }
        return null;
    }
}

4.注解类TestAnnotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestAnnotation {
    boolean flag() default true;
}

使用pointcut代码:

package com.aspectj.test.advice;
 
import java.util.Arrays;
 
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.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
 
@Aspect
public class AdviceTest {
    @Around("execution(* com.abc.service.*.many*(..))")
    public Object process(ProceedingJoinPoint point) throws Throwable {
        System.out.println("@Around:执行目标方法之前...");
        //访问目标方法的参数:
        Object[] args = point.getArgs();
        if (args != null && args.length > 0 && args[0].getClass() == String.class) {
            args[0] = "改变后的参数1";
        }
        //用改变后的参数执行目标方法
        Object returnValue = point.proceed(args);
        System.out.println("@Around:执行目标方法之后...");
        System.out.println("@Around:被织入的目标对象为:" + point.getTarget());
        return "原返回值:" + returnValue + ",这是返回结果的后缀";
    }
    
    @Before("execution(* com.abc.service.*.many*(..))")
    public void permissionCheck(JoinPoint point) {
        System.out.println("@Before:模拟权限检查...");
        System.out.println("@Before:目标方法为:" + 
                point.getSignature().getDeclaringTypeName() + 
                "." + point.getSignature().getName());
        System.out.println("@Before:参数为:" + Arrays.toString(point.getArgs()));
        System.out.println("@Before:被织入的目标对象为:" + point.getTarget());
    }
    
    @AfterReturning(pointcut="execution(* com.abc.service.*.many*(..))", 
        returning="returnValue")
    public void log(JoinPoint point, Object returnValue) {
        System.out.println("@AfterReturning:模拟日志记录功能...");
        System.out.println("@AfterReturning:目标方法为:" + 
                point.getSignature().getDeclaringTypeName() + 
                "." + point.getSignature().getName());
        System.out.println("@AfterReturning:参数为:" + 
                Arrays.toString(point.getArgs()));
        System.out.println("@AfterReturning:返回值为:" + returnValue);
        System.out.println("@AfterReturning:被织入的目标对象为:" + point.getTarget());
        
    }
    
    @After("execution(* com.abc.service.*.many*(..))")
    public void releaseResource(JoinPoint point) {
        System.out.println("@After:模拟释放资源...");
        System.out.println("@After:目标方法为:" + 
                point.getSignature().getDeclaringTypeName() + 
                "." + point.getSignature().getName());
        System.out.println("@After:参数为:" + Arrays.toString(point.getArgs()));
        System.out.println("@After:被织入的目标对象为:" + point.getTarget());
    }
}

使用annotation代码:

//注解实体类
package com.trip.demo;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
 
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface SMSAndMailSender {
    /*短信模板String格式化串*/
    String value() default "";
 
    String smsContent() default "";
 
    String mailContent() default "";
    /*是否激活发送功能*/
    boolean isActive() default true;
    /*主题*/
    String subject() default "";
}
 
 
 
//切面类
@Aspect
@Component("smsAndMailSenderMonitor")
public class SMSAndMailSenderMonitor {
 
    private Logger logger = LoggerFactory.getLogger(SMSAndMailSenderMonitor.class);
 
 
    /**
     * 在所有标记了@SMSAndMailSender的方法中切入
     * @param joinPoint
     * @param result
     */
    @AfterReturning(value="@annotation(com.trip.demo.SMSAndMailSender)", returning="result")//有注解标记的方法,执行该后置返回
    public void afterReturning(JoinPoint joinPoint , Object result//注解标注的方法返回值) {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        boolean active = method.getAnnotation(SMSAndMailSender.class).isActive();
        if (!active) {
            return;
        }
        String smsContent = method.getAnnotation(SMSAndMailSender.class).smsContent();
        String mailContent = method.getAnnotation(SMSAndMailSender.class).mailContent();
        String subject = method.getAnnotation(SMSAndMailSender.class).subject();
       
    }
    
    /**
     * 在抛出异常时使用
     * @param joinPoint
     * @param ex
     */
    @AfterThrowing(value="@annotation(com.trip.order.monitor.SMSAndMailSender)",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Throwable ex//注解标注的方法抛出的异常) {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        String subject = method.getAnnotation(SMSAndMailSender.class).subject();
        
    }
}
//实体类中使用该注解标注方法
@Service("testService ")
public class TestService {
    @Override
    @SMSAndMailSender(smsContent = "MODEL_SUBMIT_SMS", mailContent =     
    "MODEL_SUPPLIER_EMAIL", subject = "MODEL_SUBJECT_EMAIL")
    public String test(String param) {
        return "success";
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值