03.Spring_AOP

1.需要导入的jar包
     spring-beans- 4.0 .0. RELEASE . jar
     spring -context- 4.0 .0.RELEASE. jar
     spring -core- 4.0 .0.RELEASE. jar
     spring -expression- 4.0 .0. RELEASE . jar
    commons-logging- 1.1 .3. jar
     spring -aop- 4.0 .0. RELEASE . jar
    
      //以下是AOP需要额外导入的jar包
     com .springsource.net .sf.cglib- 2.2 .0. jar
     com .springsource.org .aopalliance- 1.0 .0. jar
     com .springsource.org .aspectj.weaver- 1.6 .8.RELEASE. jar
     spring -aspects- 4.0 .0.RELEASE. jar
2.AOP中的注解
  • @Aspect
    • 声明某一个类是一个切面类
    • 声明为切面类的同时还需要交给IOC容器管理
@Aspect // 声明当前类是一个切面类
@Component // 将当前类交给IOC容器管理
public class LoggingAspect {
  • @Pointcut
    • 声明切入点表达式
//声明切入点表达式
@Pointcut ( "execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))" )
public void pointCut(){};
  • @Before
    • 声明前置通知
    • 前置通知在方法执行之前调用
// 前置通知,在目标方法调用之前执行
     @Before (value = "pointCut()" )
     public void beforeAdvice(JoinPoint jp ) {
          // 获取方法名
         String name = jp .getSignature().getName();
          // 获取参数
         Object[] args = jp .getArgs();
         System. out .println( "[★★★Logging]The method " + name + " begins with " + Arrays. asList ( args ));
    }
  • @After
    • 声明后置通知
    • 后置通知在方法执行完成后调用(不管是否发生异常)
// 后置通知,在目标方法执行完成之后执行(不管是否发生异常)
     @After ( "pointCut()" )
     public void afterAdvice(JoinPoint jp ) {
          // 获取方法名
         String name = jp .getSignature().getName();
         System. out .println( "[★★★Logging]The method " + name + " ends" );
    }
  • @AfterReturning
    • 声明返回通知
    • 返回通知在方法执行完之后调用
//返回通知,在目标方法执行后执行
     @AfterReturning (pointcut = "execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))" ,returning= "result" )
     public void returnAdvice(JoinPoint jp , Object result ) {
          // 获取方法名
         String name = jp .getSignature().getName();
         System. out .println( "[★★★Logging]The method " + name + " returns " + result );
    }
  • @AfterThrowing
    • 声明异常通知
    • 异常通知在方法执行出现异常时调用
//异常通知,在目标方法执行出现异常时执行
     @AfterThrowing (pointcut = "execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))" ,throwing= "e" )
     public void returnAdvice(JoinPoint jp , Exception e ) {
          // 获取方法名
         String name = jp .getSignature().getName();
         System. out .println( "[★★★Logging]The method " + name + " occours " + e );
    }
  • @Around(使用环绕通知必须将前面的前后等方法注掉)
    • 声明环绕通知
    • 环绕通知相当于动态代理的全过程
//环绕通知,相当于动态代理的全过程
     @Around ( "pointCut()" )
     public Object roundAdvice(ProceedingJoinPoint pjp ) {
          //获取方法名
         String name = pjp .getSignature().getName();
          //获取参数
         Object[] args = pjp .getArgs();
         Object result = null ;
          try {
              //前置通知
             System. out .println( "[★★★★★Logging]The method " + name + " begins with " + Arrays. asList ( args ));
              //执行目标方法
              result = pjp .proceed();
              //返回通知
             System. out .println( "[★★★★★Logging]The method " + name + " returns " + result );
         } catch (Throwable e ) {
              //异常通知
             System. out .println( "[★★★★★Logging]The method " + name + " occours " + e );
//           e.printStackTrace();
         } finally {
              //后置通知
             System. out .println( "[★★★★★Logging]The method " + name + " ends" );
         }
          return result ;
    }
  • @Order
    • 声明切面的优先级
    • 通过该注解中的value属性值来设置切面的优先级,里面传入一个int类型的值,值越小优先级越高,默认值是Integer的最大值
@Order (10) //可以通过@Order注解中的value属性设置切面的优先级,value属性值越小优先级越高,默认值是Integer的最大值
@Aspect // 声明当前类是一个切面类
@Component // 将当前类交给IOC容器管理
public class ValidateAspect {
  • Spring的配置文件中的配置
<? xml version = "1.0" encoding = "UTF-8" ?>
     xmlns:context = " http://www.springframework.org/schema/context" ;
    
     <!-- 设置自动扫描的包 -->
     < context:component-scan base-package = "com.atguigu.spring.aop" ></ context:component-scan >
    
     <!-- 启用 AspectJ 注解支持:Spring会自动创建代理对象 -->
      < aop:aspectj-autoproxy ></ aop:aspectj-autoproxy >
</ beans >
package com.atguigu.spring.aop;
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.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect // 声明当前类是一个切面类
@Component // 将当前类交给IOC容器管理
public class LoggingAspect {
    
    //声明切入点表达式
    @Pointcut("execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))")
    public void pointCut(){};
    /**
     * 切入点表达式的表示方式: ①execution(public int
     * com.atguigu.spring.aop.ArithmeticCalculator.add(int, int))
     * execution(public int ArithmeticCalculator.add(int, int))
     * -只有调用ArithmeticCalculator接口中的add()方法时才会执行对应的通知 -如果切面类与接口和实现类在同一个包下,包名可以省略
     * ②execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int,
     * int)) --只有调用ArithmeticCalculator接口中的所有的方法时都会会执行对应的通知 ③execution(*
     * com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))
     * --调用ArithmeticCalculator接口中的所有的方法时都会会执行对应的通知,而且不考虑权限修饰符和返回值类型
     * ④execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))
     * --调用ArithmeticCalculator接口中的所有的方法时都会会执行对应的通知,而且不考虑权限修饰符和返回值类型以及参数的类型和个数
     * ⑤execution(* *.*(..)) --调用所有接口的方法时都会会执行对应的通知,而且不考虑权限修饰符和返回值类型以及参数的类型和个数
     *
     */
    // 前置通知,在目标方法调用之前执行
    @Before(value = "pointCut()")
    public void beforeAdvice(JoinPoint jp) {
        // 获取方法名
        String name = jp.getSignature().getName();
        // 获取参数
        Object[] args = jp.getArgs();
        System.out.println("[★★★Logging]The method " + name + " begins with " + Arrays.asList(args));
    }
    // 后置通知,在目标方法执行完成之后执行(不管是否发生异常)
    @After("pointCut()")
    public void afterAdvice(JoinPoint jp) {
        // 获取方法名
        String name = jp.getSignature().getName();
        System.out.println("[★★★Logging]The method " + name + " ends");
    }
    //返回通知,在目标方法执行后执行
    @AfterReturning(pointcut = "execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))",returning="result")
    public void returnAdvice(JoinPoint jp , Object result) {
        // 获取方法名
        String name = jp.getSignature().getName();
        System.out.println("[★★★Logging]The method " + name + " returns "+result);
    }
    
    //异常通知,在目标方法执行出现异常时执行
    @AfterThrowing(pointcut = "execution(* com.atguigu.spring.aop.ArithmeticCalculator.*(..))",throwing="e")
    public void returnAdvice(JoinPoint jp , Exception e) {
        // 获取方法名
        String name = jp.getSignature().getName();
        System.out.println("[★★★Logging]The method " + name + " occours "+e);
    }
    
    //环绕通知,相当于动态代理的全过程
    @Around("pointCut()")
    public Object roundAdvice(ProceedingJoinPoint pjp) {
        //获取方法名
        String name = pjp.getSignature().getName();
        //获取参数
        Object[] args = pjp.getArgs();
        Object result = null;
        try {
            //前置通知
            System.out.println("[★★★★★Logging]The method " + name + " begins with " + Arrays.asList(args));
            //执行目标方法
            result = pjp.proceed();
            //返回通知
            System.out.println("[★★★★★Logging]The method " + name + " returns "+result);
        } catch (Throwable e) {
            //异常通知
            System.out.println("[★★★★★Logging]The method " + name + " occours "+e);
//            e.printStackTrace();
        } finally{
            //后置通知
            System.out.println("[★★★★★Logging]The method " + name + " ends");
        }
        return result;
    }
    
    
}

test
package com.atguigu.spring.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.atguigu.spring.aop.ArithmeticCalculator;
public class AopTest {
    // 创建IOC容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans-aop.xml");
    @Test
    public void testAOP() {
        ArithmeticCalculator atc = (ArithmeticCalculator) ioc.getBean("arithmeticCalculator");
        // 进行加、减、乘、除的运算
        int add = atc.add(10, 2);
        System.out.println(add);
        int sub = atc.sub(10, 2);
        System.out.println(sub);
        int mul = atc.mul(10, 2);
        System.out.println(mul);
        int div = atc.div(10, 0);
        System.out.println(div);
    }
}

3.基于XML的形式配置AOP
<? xml version = "1.0" encoding = "UTF-8" ?>
     <!-- 配置数学计算器的实现类bean -->
     < bean id = "arithmeticCalculator" class = "com.atguigu.spring.xml.ArithmeticCalculatorImpl" ></ bean >
    
     <!-- 配置切面类bean -->
     < bean id = "loggingAspect" class = "com.atguigu.spring.xml.LoggingAspect" ></ bean >
    
     <!-- 配置AOP -->
     < aop:config >
          <!-- 配置切入点表达式 -->
          < aop:pointcut expression = "execution(* com.atguigu.spring.xml.ArithmeticCalculator.*(..))"
              id = "pointCut" />
          <!-- 配置切面 -->
          < aop:aspect ref = "loggingAspect" >
              <!-- 前置通知 -->
              < aop:before method = "beforeAdvice" pointcut-ref = "pointCut" />
              <!-- 后置通知 -->
              < aop:after method = "afterAdvice" pointcut-ref = "pointCut" />
              <!-- 返回通知 -->
              < aop:after-returning method = "returnAdvice" pointcut-ref = "pointCut" returning = "result" />
              <!-- 异常通知 -->
              < aop:after-throwing method = "exceptionAdvice" pointcut-ref = "pointCut" throwing = "e" />
              <!-- 环绕通知 -->
              < aop:around method = "roundAdvice" pointcut-ref = "pointCut" />
          </ aop:aspect >
     </ aop:config >
</ beans >
package com.atguigu.spring.xml;
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.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
public class LoggingAspect {
    
    // 前置通知,在目标方法调用之前执行
    public void beforeAdvice(JoinPoint jp) {
        // 获取方法名
        String name = jp.getSignature().getName();
        // 获取参数
        Object[] args = jp.getArgs();
        System.out.println("[▲Logging]The method " + name + " begins with " + Arrays.asList(args));
    }
    // 后置通知,在目标方法执行完成之后执行(不管是否发生异常)
    public void afterAdvice(JoinPoint jp) {
        // 获取方法名
        String name = jp.getSignature().getName();
        System.out.println("[▲Logging]The method " + name + " ends");
    }
    //返回通知,在目标方法执行后执行
    public void returnAdvice(JoinPoint jp , Object result) {
        // 获取方法名
        String name = jp.getSignature().getName();
        System.out.println("[▲Logging]The method " + name + " returns "+result);
    }
    
    //异常通知,在目标方法执行出现异常时执行
    public void exceptionAdvice(JoinPoint jp , Exception e) {
        // 获取方法名
        String name = jp.getSignature().getName();
        System.out.println("[▲Logging]The method " + name + " occours "+e);
    }
    
    //环绕通知,相当于动态代理的全过程
    public Object roundAdvice(ProceedingJoinPoint pjp) {
        //获取方法名
        String name = pjp.getSignature().getName();
        //获取参数
        Object[] args = pjp.getArgs();
        Object result = null;
        try {
            //前置通知
            System.out.println("[▲▲Logging]The method " + name + " begins with " + Arrays.asList(args));
            //执行目标方法
            result = pjp.proceed();
            //返回通知
            System.out.println("[▲▲Logging]The method " + name + " returns "+result);
        } catch (Throwable e) {
            //异常通知
            System.out.println("[▲▲Logging]The method " + name + " occours "+e);
//            e.printStackTrace();
        } finally{
            //后置通知
            System.out.println("[▲▲Logging]The method " + name + " ends");
        }
        return result;
    }
    
}

test
package com.atguigu.spring.test;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.atguigu.spring.xml.ArithmeticCalculator;
public class Aop_xmlTest {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans-xml.xml");
    @Test
    public void testAOP_xml() {
        ArithmeticCalculator atc = (ArithmeticCalculator) ioc.getBean("arithmeticCalculator");
        // 进行加、减、乘、除的运算
        int add = atc.add(10, 2);
        System.out.println(add);
        int sub = atc.sub(10, 2);
        System.out.println(sub);
        int mul = atc.mul(10, 2);
        System.out.println(mul);
        int div = atc.div(10, 2);
        System.out.println(div);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值