sping-aop(注解顶流方式)

10 篇文章 0 订阅
9 篇文章 0 订阅

想要使用spring中的任何技术 第一步都需要导包

第一步导包

  • spring核心包
  • spring整个aspectj
  • lombok偷懒神器
  • 测试包junit
  • spring集合junit4

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.17</version>
        </dependency>
    </dependencies>

第二步 开始创建使用aop

  • 首先是创建spring的配置文件
  • 目的就是开启注解配置 包扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <context:component-scan base-package="com.cong"></context:component-scan>

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

 创建一个目标对象

  • 目标对象解释:被通知的对象称之为目标对象

接口

/**
 * @ClassName CalculatorDao
 * @Author Dongyu Zhou
 * @Date 2022/4/24 19:25
 * @Version 1.0
 */
public interface CalculatorDao {
    /**
     * 加法
     * @param a
     * @param b
     */
    public int add(int a ,int b);

    /**
     * 减法
     * @param a
     * @param b
     */
    public int sub(int a ,int b);
}

实现类

/**
 * @ClassName CalucDaoImpl
 * @Author Dongyu Zhou
 * @Date 2022/4/24 19:25
 * @Version 1.0
 */
@Repository
public class CalucDaoImpl implements CalculatorDao {

    @Override
    public int add(int a, int b) {
        System.out.println("add-------------");
        return a+b;
    }

    @Override
    public int sub(int a, int b) {
        System.out.println("sub-------------");
        return a-b;
    }
}

创建切面

  • 名词解释 切面:非核心业务代码称之为:通知【提取到切面之后】
/**
 * @ClassName MyProxy
 * @Author Dongyu Zhou
 * @Date 2022/4/24 19:27
 * @Version 1.0
 */
@Component
@Aspect
public class MyProxy {
    //加一个日志功能
    /**
     * 提取公共代码
     */
    @Pointcut("execution(* com.cong.dao.impl.*.*(..))")
    public void myPorxy(){}

    /**
     * 前置通知
     * joinPoint.getSignature() 获取签名   public int add(int a, int b) 方法名加参数
     */
    @Before("myPorxy()")
    public void before(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("前置通知 方法名是:"+name+"  参数是"+ Arrays.toString(args));
    }

    /**
     * 后置通知
     * @param joinPoint
     */
    @After("myPorxy()")
    public void after(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("后置通知 方法名是:"+name+"  参数是"+ Arrays.toString(args));
    }

    /**
     * 返回通知 定义一个返回参数
     * @param joinPoint
     */
    @AfterReturning(value = "myPorxy()",returning = "ret")
    public void afterReturning(JoinPoint joinPoint,Object ret){
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("返回通知 方法名是:"+name+"  参数是"+ Arrays.toString(args)+"   返回值是:"+ret);
    }

    /**
     * 异常通知
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "myPorxy()",throwing = "e")
    public void afterReturning(JoinPoint joinPoint,Throwable e){
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("返回通知 方法名是:"+name+"  参数是"+ Arrays.toString(args));
    }

    /**
     * 终极大法 环绕通知
     */
    @Around(value = "myPorxy()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        String name = proceedingJoinPoint.getSignature().getName();
        Object[] args = proceedingJoinPoint.getArgs();
        Object proceed = null;
        try {
            //前置通知
            System.out.println("前置通知 方法名是:"+name+"  参数是"+ Arrays.toString(args));
            proceed = proceedingJoinPoint.proceed();
            //返回通知
            System.out.println("返回通知 方法名是:"+name+"  参数是"+ Arrays.toString(args));
        } catch (Throwable e) {
            //异常通知
            System.out.println("返回通知 方法名是:"+name+"  异常是"+ e);
        } finally {
            //后置通知
            System.out.println("后置通知 方法名是:"+name+"  参数是"+ Arrays.toString(args));
        }


        return proceed;

    }
}

测试

/**
 * @ClassName MyTest
 * @Author Dongyu Zhou
 * @Date 2022/4/24 19:36
 * @Version 1.0
 */
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class MyTest {

    @Autowired
    private CalculatorDao calculatorDao;

    @Test
    public void before() {
        int add = calculatorDao.add(1, 2);
    }

    @Test
    public void after() {
        int sub = calculatorDao.sub(20, 2);
    }
}

这里 总结下

前置通知: 没什么可注意的 加一个参数 JoinPoint 这里可以获取类的签名

类的签名就是类名加参数 都可以获取到

注意的是在切点执行之前执行 所以有异常也会执行

 



 

 后置通知 

需要注意的是 后置通知是最后执行的 不管有没有异常都会执行

 



返回通知

这里返回通知就是可以有一个返回值

需要加一个参数

@AfterReturning(value = "myPorxy()",returning = "ret")

这个参数名字ret可以随便叫 你喜欢就行 但是必须和方法中的Object中的形参名形同

有异常不会执行

 



 异常通知

顾名思义就是有异常才会执行 没有异常不会执行

这里和返回通知同样有一个参数值 是异常类型的形参 可以随便叫什么名字



 

 前面四个通知有一个总结性的通知

叫做环绕通知  需要注意两点

第一点就是必须要有一个返回值类型 必须和目标方法返回值类型一直 用Object

第二点就是必须加一个参数

ProceedingJoinPoint 

执行方法

proceed = proceedingJoinPoint.proceed();

代表目标对象方法的执行  所以给他一个try catch finally

分别加上前置通知 返回通知 异常通知 和后置通知

 



 四个通知的执行流程

有异常的情况下 : 前置通知->异常->后置

无异常的情况下 : 前置 ->返回->后置

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值