Spring-AOP例子

Spring-AOP例子

第一部分是前期准备,第二部分是基于注解的方式配置事务,第三部分基于.xml配置文件配置事务

一、准备

使用加减乘除方法测试,测试AOP

1.1 概览

在这里插入图片描述
在这里插入图片描述

1.2 jar包介绍 (lib)

在这里插入图片描述

junit测试
junit-4.12.jar
hamcrest-core-1.3.jar
Spring核心容器(4个:Beans,Core,Context,expression)
spring-beans-5.3.1.jar
spring-context-5.3.1.jar
spring-core-5.3.1.jar----->依赖于jar包spring-jcl-5.3.1.jar
spring-expression-5.3.1.jar
Spring aop
spring-aop-5.3.1.jar
spring-aspect-5.3.1.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
JdbcTemplate
spring-jdbc-5.3.1.jar
spring-orm-5.3.1.jar
spring-tx-5.3.1.jar
连接数据库的驱动jar包和数据源
mysql-connector-java-5.1.37-bin.jar
druid-1.1.9.jar

1.3 方法(Calculator)

public interface Calculator {
    int add(int a,int b);
    int sub(int a,int b);
    int mul(int a,int b);
    int div(int a,int b);
}

1.4 实现类(CalculatorImpl)

public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }

    @Override
    public int mul(int a, int b) {
        return a * b;
    }

    @Override
    public int div(int a, int b) {
        return a / b;
    }
}

二、基于注解的方式配置事务

2.1 在实现类中添加@Controller注解 (CalculatorImpl)

@Controller("coc")
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }

    @Override
    public int mul(int a, int b) {
        return a * b;
    }

    @Override
    public int div(int a, int b) {
        return a / b;
    }
}

2.2 通知事务 (LoggingAspect)

@Controller//交给Spring的IOC容器管理
@Aspect//声明该类是一个切面
public class LoggingAspect {

	//声明切入点表达式,在使用的地方通过方法名引用即可
    @Pointcut(value = "execution(* com.spring.aop.aspect.Calculator.*(..))")
    public void pointCut() {
    }

	//前置通知,在方法执行之前执行
    @Before(value = "pointCut()")
    public void beforeAdvice(JoinPoint joinPoint){
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        //获取参数
        Object[] args = joinPoint.getArgs();
        System.out.println("前置通知: "+methodName+" 方法,参数: "+ Arrays.toString(args));
    }

    //后置通知,在方法执行之后执行,不管是否发生异常
    @After("pointCut()")
    public void afterAdvice(JoinPoint joinPoint){
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        System.out.println("后置通知: "+methodName+" 方法");
    }

    //返回通知,在方法返回结果之后执行
    //pointcut属性:指定切入点表达式,跟value属性功能一样;returning属性:获取方法的返回值,并指定通知方法中入参的形参名
    @AfterReturning(pointcut = "pointCut()",returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result){
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        System.out.println("返回通知: "+methodName+" 方法,返回: "+result);
    }

    //异常通知,在方法执行抛出异常时执行
    //pointcut属性:指定切入点表达式,跟value属性功能一样;throwing属性:获取异常信息,并指定通知方法中入参的形参名
    @AfterThrowing(value = "execution(* Calculator.*(..))",throwing = "e")
    public void afterThrowing(JoinPoint joinPoint,Throwable e){
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        System.out.println("异常通知: "+methodName+" 方法,异常: "+e);
    }
}

2.3 .xml配置 (calculator.xml)

<?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 
       https://www.springframework.org/schema/context/spring-context.xsd 
       http://www.springframework.org/schema/aop 
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--开启自动扫描包-->
    <context:component-scan base-package="com.spring.aop.aspect"/>

    <!--开启通知-->
    <aop:aspectj-autoproxy/>
</beans>

2.4 测试类 (testCalculator)

public class testCalculator {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("calculator.xml");

    @Test
    public void test01() {
        Calculator calculator = (Calculator) ioc.getBean("coc");

        calculator.add(10, 2);//加
        calculator.sub(10, 2);//减
        calculator.mul(10, 2);//乘
        calculator.div(10, 0);//除:测试异常通知
    }
}

2.5 输出

在这里插入图片描述

改进为环绕通知

2.6 改进通知事务 (LoggingAspect)为环绕通知

@Controller
@Aspect
public class LoggingAspect {
    @Pointcut(value = "execution(* com.spring.aop.aspect.Calculator.*(..))")
    public void pointCut() {
    }
    
    //环绕通知,相当于动态代理的全过程
    @Around(value = "pointCut()")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
        //获取方法名
        String methodName = proceedingJoinPoint.getSignature().getName();
        //获取参数
        Object[] args = proceedingJoinPoint.getArgs();
        Object result = null;
        try {
        	//前置通知
            System.out.println("前置通知: "+methodName+" 方法,参数: "+ Arrays.toString(args));
            //执行被代理对象的方法
            result = proceedingJoinPoint.proceed();
            //返回通知
            System.out.println("返回通知: "+methodName+" 方法,返回: "+result);
        } catch (Throwable e) {
        	//异常通知
            System.out.println("异常通知: "+methodName+" 方法,异常: "+e);
            e.printStackTrace();
        } finally {
        	//后置通知
            System.out.println("后置通知: "+methodName+" 方法");
        }
        return result;
    }
}

2.7 切面执行顺序

如果有两个事务通知,要规定其先后顺序就可以使用@Order()注解,设置value参数,越小执行越靠前,默认值为2147483647。
在切面类中直接注解
在这里插入图片描述

三、基于.xml配置文件配置事务

3.1 还原实现类(CalculatorImpl

public class CalculatorImpl implements Calculator{

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }

    @Override
    public int mul(int a, int b) {
        return a * b;
    }

    @Override
    public int div(int a, int b) {
        return a / b;
    }
}

3.2 事务通知(LoggingAspect)

public class LoggingAspect {
    //前置通知
    public void beforeAdvice(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("前置通知:" + methodName + "方法,参数为:" + Arrays.toString(args));
    }

    //后置通知
    public void afterAdvice(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("后置通知:" + methodName + "方法。");
    }

    //异常通知
    public void afterThrowing(JoinPoint joinPoint, Throwable e) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("异常通知:" + methodName + "方法,异常:" + e);
    }

    //返回通知
    public void afterReturning(JoinPoint joinPoint,Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("返回通知:" + methodName+"方法,结果为:" + result);
    }
}

3.3 .xml配置 (calculator-xml.xml)

<?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: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/aop 
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="calculator" class="com.spring.aop.aspect.aop.CalculatorImpl"/>

    <bean id="loggingAspect2" class="com.spring.aop.aspect.aop.LoggingAspect"/>

    <aop:config>
        <aop:pointcut id="pointCut" expression="execution(* com.spring.aop.aspect.xml.CalculatorImpl.*(..))"/>
        <aop:aspect ref="loggingAspect2">
        	<!--前置通知-->
            <aop:before method="beforeAdvice" pointcut-ref="pointCut"/>
            <!--后置通知-->
            <aop:after method="afterAdvice" pointcut-ref="pointCut"/>
            <!--返回通知-->
            <aop:after-returning method="afterReturning" pointcut-ref="pointCut" returning="result"/>
            <!--异常通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointCut" throwing="e"/>
        </aop:aspect>
    </aop:config>
</beans>

3.4 测试类 (testCalculator-xml)

public class TestCalculator {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("calculator-xml.xml");

    @Test
    public void test01(){
        Calculator calculator = (Calculator) ioc.getBean("calculator");
        calculator.add(10, 2);
        calculator.sub(10, 2);
        calculator.mul(10, 2);
        calculator.div(10, 0);
    }
}

3.5 改进通知事务 (LoggingAspect)为环绕通知

public class LoggingAspect {
	//环绕通知,相当于动态代理的全过程
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        //获取方法名
        String methodName = proceedingJoinPoint.getSignature().getName();
        //获取参数
        Object[] args = proceedingJoinPoint.getArgs();
        Object result=null;
        try {
            //前置通知
            System.out.println("前置通知:" + methodName + "方法,参数为:" + Arrays.toString(args));
            //执行被代理对象的方法
            result = proceedingJoinPoint.proceed();
            //返回通知
            System.out.println("返回通知:" + methodName+"方法,结果为:" + result);
        } catch (Throwable e) {
            //异常通知e
            System.out.println("异常通知:" + methodName + "方法,异常:" + e);
            e.printStackTrace();
        } finally {
            //后置通知
            System.out.println("后置通知:" + methodName + "方法。");
        }
        return result;
    }
}

3.6 修改配置文件 (calculator-xml

<?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: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/aop 
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="calculator" class="com.spring.aop.aspect.xml.CalculatorImpl"/>

    <bean id="loggingAspect" class="com.spring.aop.aspect.xml.LoggingAspect"/>

    <aop:config>
        <aop:pointcut id="pointCut" expression="execution(* com.spring.aop.aspect.xml.CalculatorImpl.*(..))"/>
        <aop:aspect ref="loggingAspect">
            <!--<!--前置通知-->
            <aop:before method="beforeAdvice" pointcut-ref="pointCut"/>
            <!--后置通知-->
            <aop:after method="afterAdvice" pointcut-ref="pointCut"/>
            <!--返回通知-->
            <aop:after-returning method="afterReturning" pointcut-ref="pointCut" returning="result"/>
            <!--异常通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointCut" throwing="e"/>-->
            <!--环绕通知-->
            <aop:around method="aroundAdvice" pointcut-ref="pointCut"/>
    </aop:config>
</beans>

3.7 输出

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sunset、筱虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值