Spring-Aop

发布时间 2023-08-17 10:30:40作者: PHOEDE

   1、面向切面编程Aspect,通过预编译方式和运行期间动态代理实现程序的统一维护的一种技术 

   2、AOP应用场景

        (1) 记录日志

        (2) 权限校验

        (3) Spring事务管理

   3、AOP的结构

        AOP要做的三件事,在哪里切入,也就是权限校验,等非业务操作在哪些业务代码中执行;什么时候切入,是业务代码执行前还是执行后;切入后做什么事,比如做权限校验、日志记录等。

          

        (1) Aspect : 切面

        (2) PointCut : 切点  ---方式:1、路径表达式   2、注解形式

        (3) Advice: 处理的时机。

  4、路径表达式使用AOP

       4.1、路径表达式

   

@Aspect//标记该类为切面类
@Component//该类对象的创建交于Spring容器来管理同类有@service @Controller
public class aop1 {
    /**
     * @Pointcut(value = "execution(public double comm.aop.MathServiceImpl.jia(double ,double ))")  
     * 第一个 * :表示任意修饰符   任意返回类型
     * 第二个 * : 表示该包下所有的类
     * 第三个 * : 类下所有的方法
     *  (..)    表示任意参数
     
     */
   @Pointcut(value = "execution(* comm.aop*.*(.. ))")
    private void mypointcut(){}
    @After(value = "mypointcut()")
    public void b(){
        System.out.println("AAAAAAAAA");
    }
}

Service:

public interface Mathservice {
    public double jia(double a, double b);
    public double jian(double a, double b);
    public double Cheng(double a, double b);
    public double chu(double a, double b);
}

ServiceImpl:

@Service
public class MathServiceImpl implements Mathservice {
    @Override
    public double jia(double a, double b) {
        double result=a+b;
        System.out.println("AAA--->The add method result="+result);
        return result;
    }
    @Override
    public double jian(double a, double b) {
        double result=a-b;
        System.out.println("AAA--->The add method result="+result);
        return result;
    }
    @Override
    public double Cheng(double a, double b) {
        double result=a * b;
        System.out.println("AAA--->The add method result="+result);
        return result;
    }
    @Override
    public double chu(double a, double b) {
        double result=a/b;
        System.out.println("AAA--->The add method result="+result);
        return result;
    }
}

测试:

public class Text {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring.xml");
        Mathservice mathServiceImpl =(Mathservice) context.getBean("mathServiceImpl");
        System.out.println(mathServiceImpl.jia(20, 10));
    }
}

    

    4.2、注解表达式

          (1) 自定义注解

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "";
}

          (2) 修改切面类

@Pointcut(value = "@annotation(comm.aop.MyAnnotation)")
private void mypointcut(){}
@After(value = "mypointcut()")
public void b(){
    System.out.println("AAAAAAAAA");
}

    5、AOP切面通知的类型

                

              @Before 前置通知. 被代理的方法执行前--执行

//前置通知:
@Before(value = "mypointcut()")
public void a(){
    System.out.println("方法执行前执行切面的内容,前置通知");
}

 

              @After: 后置通知: 被代理的方法执行完后--执行

//后置返回通知,碰到return,如果方法出现异常;这种通知不会被执行
@After(value = "mypointcut()")
public void b(){
    System.out.println("AAAAAAAAA");
}

              @AfterReturning: 后置返回通知: 被代理的方法碰到return.--才会执行

//后置返回通知,碰见return,如果方法出现异常;这种通知不会被执行
@AfterReturning(value = "mypointcut()",returning = "t")//returning 它会把方法执行的结果赋值给该变量
public void afterReturning(Object t){
    System.out.println("后置返回通知:"+t);
}

     执行结果:

          

              @AfterThrowing: 后置异常通知: 当被代理的方法出现异常时--才会执行。

//异常通知:当被切入的方法出现异常时,才会执行
@AfterThrowing(value = "mypointcut()")
public void afterThrowing(){
    System.out.println("异常通知");
}

      异常执行结果:

         

              @Around: 环绕通知。

//环绕通知
@Around(value = "mypointcut()")
//joinPoint:连接点 理解为被执行的方法对象
public Object around(ProceedingJoinPoint joinPoint){
    System.out.println("业务代码执行前的内容");
    try {
        Object proceed = joinPoint.proceed();//执行的连接点
        System.out.println("方法执行完毕后");
        return proceed;
    } catch (Throwable throwable) {
        throwable.printStackTrace();
        System.out.println("方法出现异常代码执行异常");
    } finally {
        System.out.println("代码都会执行的地方");
    }
    return 0.0;
}

    环绕执行结果: