Spring AOP-高级详解【注意了哦】

谁都会走 提交于 2020-05-03 23:35:01

Spring AOP-高级

来,直上案例说明:  咻咻........

一. 高级案例1:定义公共切入点

简述

切面类中会有很多通知,大部分通知的切入点都是相同的。

为了切入点 管理和维护更加方便,使用公共切入点。

@Pointcut

方法的修饰符:private

方法的返回值:void

方法无参数

方法无方法体

 

代码实现

切面类:  (注意:标黄色是基于上篇新增的代码)

@Component
@Aspect
public class MyAspect {
    @Pointcut("execution(* com.czxy.demo1.service..*.*(..))")
    private void myCut1(){}

    @AfterThrowing(value="myCut1()",throwing = "ex")
    public void a1(JoinPoint joinPoint,Throwable ex){
        System.out.println("异常通知:"+joinPoint.getSignature().getName()+"方法出异常了"+ex.getMessage());
    }
    @AfterReturning(value="myCut1()",returning = "obj")
    public void a2(JoinPoint joinPoint,Object obj){
        System.out.println("后置通知:"+joinPoint.getSignature().getName()+"方法返回值值是:"+obj);
    }
}

 

 

二. 高级案例2:定义完整的切面类

代码实现

配置类:

@Configuration
@ComponentScan(basePackages = {"com.czxy.demo2"})
@EnableAspectJAutoProxy
public class SpringConfiguration {
}

 

切面类:

@Component
@Aspect
public class MyAspect {
    /*
    * 定义公共切入点
    * */
    @Pointcut("execution(* com.czxy.demo2.service..*.*(..))")
    private void myCut1(){}
    /*
    * 环绕通知
    * */
    @Around("myCut1()")
    public void a1(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知---连接点执行之前");
        Object proceed = pjp.proceed();
        System.out.println("环绕通知中-连接点返回值:"+proceed);
        System.out.println("环绕通知---连接点执行之后");
    }
    /*
    * 前置通知
    * */
    @Before("myCut1()")
    public void b1(JoinPoint joinPoint){
        System.out.println("前置通知---"+joinPoint.getSignature().getName());
    }

    /*
    * 最终通知
    * */
    @After("myCut1()")
    public void a2(JoinPoint joinPoint){
        System.out.println("最终通知---"+joinPoint.getSignature().getName());
    }

    /*
    * 后置通知
    * */
    @AfterReturning(value="myCut1()",returning = "obj")
    public void a3(JoinPoint joinPoint,Object obj){
        System.out.println("后置通知---"+joinPoint.getSignature().getName());
    }

    /*
    * 异常通知
    * */
    @AfterThrowing(value="myCut1()",throwing = "ex")
    public void a4(JoinPoint joinPoint,Throwable ex){
        System.out.println("异常通知---"+joinPoint.getSignature().getName()+"异常是:"+ex.getMessage());
    }
}

 

Service:

@Service
public class Demo2ServiceImpl implements Demo2Service {
    @Override
    public void test01() {
        System.out.println("---test01---");
    }
    @Override
    public String test02() {
        System.out.println("---test02---");
        return "嘤嘤嘤";
    }
    @Override
    public void test03(String a, String b) {
        System.out.println("---test03---");
        System.out.println("参数a:"+a+"\t 参数b:"+b);
    }
    @Override
    public void test04() {
        System.out.println("---test04---");
        int a=1/0;
    }
}

 

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class Demo2Test {
    @Resource
    private Demo2Service demo2Service;

    @Test
    public void run1(){
        demo2Service.test01();
        System.out.println("++++++++");
        demo2Service.test02();
        System.out.println("++++++++");
        demo2Service.test03("aa","bb");
        System.out.println("++++++++");
        demo2Service.test04();
        System.out.println("++++++++");
    }
}

 

通知的执行顺序【重点】

 

 

 

三. 高级案例3:后置通知和环绕通知的结合 (返回值传递)

代码实现

切面类

@Component

@Aspect
public class MyAspect {
    /*
    * 定义公共切入点
    * */
    @Pointcut("execution(* com.czxy.demo2.service..*.*(..))")
    private void myCut1(){}
    /*
    * 环绕通知
    * */
    @Around("myCut1()")
    public Object a1(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知---连接点执行之前");
        Object proceed = pjp.proceed();
        System.out.println("环绕通知中-连接点返回值:"+proceed);
        System.out.println("环绕通知---连接点执行之后");
        return proceed;
    }
    /*
    * 前置通知
    * */
    @Before("myCut1()")
    public void b1(JoinPoint joinPoint){
        System.out.println("前置通知---"+joinPoint.getSignature().getName());
    }

    /*
    * 最终通知
    * */
    @After("myCut1()")
    public void a2(JoinPoint joinPoint){
        System.out.println("最终通知---"+joinPoint.getSignature().getName());
    }

    /*
    * 后置通知
    * */
    @AfterReturning(value="myCut1()",returning = "obj")
    public void a3(JoinPoint joinPoint,Object obj){
        System.out.println("后置通知---"+joinPoint.getSignature().getName()+"返回值是:"+obj);
    }

    /*
    * 异常通知
    * */
    @AfterThrowing(value="myCut1()",throwing = "ex")
    public void a4(JoinPoint joinPoint,Throwable ex){
        System.out.println("异常通知---"+joinPoint.getSignature().getName()+"异常是:"+ex.getMessage());
    }
}

 

 

小结;

SpringAOP:面向切面编程。  在不修改原有代码的基础上,把新代码插入到原有代码的执行中。

连接点:被spring拦截的方法

切入点:通常是一个表达式。表示spring需要拦截的连接点有哪些

通知:拦截到连接点后要做哪些事

切面:包含切入点和通知 。  @Aspect

 

@Around:环绕通知。控制连接点是否执行

@Before:前置通知。

@After:最终通知。无论如何都一定会被执行的通知

@AfterReturning:后置通知。获取连接点的返回值。(若设置了环绕通知,环绕通知必须使用返回值的形式传递连接点返回值)

@AfterThrowring:异常通知。仅连接点出现异常时。

 

 

 

 

 

看完恭喜你,又进步了一点点!!!

你知道的越多,不知道的越多! 

~感谢志同道合的你阅读,  你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!