springAOP简单使用

  • 基于配置文件的切面配置,废话不多说,上代码
  • 涉及到的配置文件aop.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
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置aop切面,先注入切面类和被代理对象的类-->
    <bean id="sucurityUtil" class="my.utils.SucurityUtil"></bean>
    <bean id="logUtil" class="my.utils.LogUtil"></bean>
    <bean id="calculatorImpl" class="my.reflect.CalculatorImpl"></bean>
    <aop:config>
        <!--如果pointcut相同,可以抽象出公用的,每个消息通知中可以使用pointcut-ref引用-->
        <aop:pointcut id="globalpointcut" expression="execution(public Integer my.reflect.CalculatorImpl.*(..))"></aop:pointcut>
        <aop:aspect ref="sucurityUtil" order="1">
            <aop:before method="methodStartLog" pointcut-ref="globalpointcut" ></aop:before>
            <aop:after-returning method="methodStopLog" pointcut-ref="globalpointcut" returning="result"></aop:after-returning>
            <aop:after-throwing method="methodExceptionLog" pointcut-ref="globalpointcut" throwing="e"></aop:after-throwing>
            <aop:after method="methodFinallyLog" pointcut-ref="globalpointcut"></aop:after>
        </aop:aspect>
        <aop:aspect ref="logUtil" order="2">
            <aop:before method="methodStartLog" pointcut="execution(public Integer my.reflect.CalculatorImpl.*(..))" ></aop:before>
            <aop:after-returning method="methodStopLog" pointcut="execution(public Integer my.reflect.CalculatorImpl.*(..))" returning="result"></aop:after-returning>
            <aop:after-throwing method="methodExceptionLog" pointcut="execution(public Integer my.reflect.CalculatorImpl.*(..))" throwing="e"></aop:after-throwing>
            <aop:after method="methodFinallyLog" pointcut="execution(public Integer my.reflect.CalculatorImpl.*(..))"></aop:after>
        </aop:aspect>
    </aop:config>

</beans>
  • 日志切面类1
package my.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

//@Aspect
//@Component
//@Order注解可以限定多个切面的执行顺序,例如本案例中的(LogUtil和SecurityUtil)两个切面类,设置order注解的value属性,数值越小先执行,
//如果两个都没有设置order,默认是按照切面类名字典排序
//@Order(value = 1)
public class SucurityUtil {
    @Before(value = "myPointCut()")
    public static void methodStartLog(JoinPoint joinPoint){
        System.out.println("Security-->"+joinPoint.getSignature().getName()+"方法开始执行,参数为:"+ Arrays.asList(joinPoint.getArgs()));
    }

    @AfterReturning(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))",returning = "result")
    public static void methodStopLog(JoinPoint joinPoint,Object result){
        System.out.println("Security-->"+joinPoint.getSignature().getName()+"方法执行完毕,结果为:"+result);
    }

    @AfterThrowing(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))",throwing = "e")
    public static void methodExceptionLog(JoinPoint joinPoint,Exception e){
        System.out.println("Security-->"+joinPoint.getSignature().getName()+"方法出现异常:"+e.getMessage());
    }

    @After(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))")
    public static void methodFinallyLog(JoinPoint joinPoint){
        System.out.println("Security-->"+joinPoint.getSignature().getName()+"方法最终输出结果");
    }

    //定义pointCut 如果多个方法的切点表达式一致,就可以把切点表达式抽象出来:
//          定义一个没有返回值的空方法,给该方法添加@PointCut方法,后续在使用的时候可以直接调用方法名称
    @Pointcut(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))")
    public void myPointCut(){ }
}

  • 日志切面类2
package my.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;


/**
 * 通知注解有以下几种类型
 * @Before 前置通知,在指定方法执行之前执行
 * @After 后置通知,在指定方法执行之后执行
 * @AferReturning  返回通知,在返回结果之后执行
 * @AfterThrowing 异常通知,出现异常的时候使用
 * @Around  环绕通知
 *
 * 注意:在每个通知方法(add,sub,mul,div)中,不要随便添加参数值,会有异常信息
 */

//@Aspect  //声明当前类是一个切面类
//@Component  //将切面类实例添加到ioc容器中
//@Order(value = 2)
public class LogUtil {

    @Before(value = "myPointCut()")
    public static void methodStartLog(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName()+"方法开始执行,参数为-----:"+ Arrays.asList(joinPoint.getArgs()));
    }

    @AfterReturning(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))",returning = "result")
    public static void methodStopLog(JoinPoint joinPoint,Object result){
        System.out.println(joinPoint.getSignature().getName()+"方法执行完毕,结果为-----:"+result);
    }

    @AfterThrowing(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))",throwing = "e")
    public static void methodExceptionLog(JoinPoint joinPoint,Exception e){
        System.out.println(joinPoint.getSignature().getName()+"方法出现异常-----:"+e.getMessage());
    }

    @After(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))")
    public static void methodFinallyLog(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName()+"方法最终输出结果-----");
    }

    //定义pointCut 如果多个方法的切点表达式一致,就可以把切点表达式抽象出来:
//          定义一个没有返回值的空方法,给该方法添加@PointCut方法,后续在使用的时候可以直接调用方法名称
    @Pointcut(value = "execution(public Integer my.reflect.CalculatorImpl.*(Integer,Integer))")
    public void myPointCut(){ }


    //如果要修改方法执行后的返回值,就只能用环绕通知,只有环绕通知可以修改当前执行方法的返回值
   /* @Around(value = "myPointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        Signature signature = proceedingJoinPoint.getSignature();
        Object[] args = proceedingJoinPoint.getArgs();
        Object obj = null;
        try {
            System.out.println("环绕通知start-->"+signature.getName()+"方法开始执行,参数列表是:"+Arrays.asList(args));
            obj= proceedingJoinPoint.proceed();
            System.out.println("环绕通知stop-->"+signature.getName()+"方法执行结束");
        } catch (Throwable throwable) {
            System.out.println("环绕通知异常-->"+signature.getName()+"方法出现异常:"+throwable.getMessage());
            throwable.printStackTrace();
        }finally {
            System.out.println("环绕返回通知-->"+signature.getName()+"方法返回结果是:"+obj);
        }
        return obj;
    }*/
}

  • 被代理对象的父接口
package my.reflect;

import org.springframework.stereotype.Component;


public interface Calculator {

    Integer add(Integer x, Integer y) throws NoSuchMethodException;
    Integer sub(Integer x, Integer y) throws NoSuchMethodException;
    Integer mul(Integer x, Integer y) throws NoSuchMethodException;
    Integer div(Integer x, Integer y) throws NoSuchMethodException;
}

  • 被代理对象类
package my.reflect;

import org.springframework.stereotype.Component;

//被代理的类添加到IOC容器中,保证ioc容器能扫描到
//@Component 	//此处的注解可以替代aop.xml中的bean标签中注册的类
public class CalculatorImpl
 //此处是否实现父接口是决定aop采用何种方式的动态代理的关键,如果实现了父接口,那几采用jdk的
        implements Calculator  
{

    @Override
    public Integer add(Integer x, Integer y) throws NoSuchMethodException {
        int result = x + y;
        return result;
    }

    @Override
    public Integer sub(Integer x, Integer y) throws NoSuchMethodException {
        int result = x - y;
        return result;
    }

    @Override
    public Integer mul(Integer x, Integer y) throws NoSuchMethodException {
        int result = x * y;
        return result;
    }

    @Override
    public Integer div(Integer x, Integer y) throws NoSuchMethodException {
        int result = x / y;
        return result;
    }
}

  • 测试类
    @Test
    public void test02() throws NoSuchMethodException {
        //spring运用两种动态代理的方式,
        //当被代理对象时接口并有对应的实现类的时候,采用的是jdk提供的代理方式(以下写法)
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
        Calculator calculator = context.getBean("calculatorImpl", Calculator.class);
        calculator.mul(1,1);
        System.out.println(calculator.getClass());
        //当代理对象就是普通的一个类(没有实现接口)时,此时的spring采用的是CGLIB的代理方式(以下写法)
       /* ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("aop.xml");
        CalculatorImpl calculatorImpl = context1.getBean("calculatorImpl", CalculatorImpl.class);
        calculatorImpl.div(1,1);
        System.out.println(calculatorImpl.getClass());
        String s = ToStringBuilder.reflectionToString(calculatorImpl);
        System.out.println(s);*/
    }
  • 小结
    关于切面的配置和使用不仅仅局限于在配置文件中的使用,使用注解时完全可以取代配置文件的,这里仅仅是简单的一个demo,关于更多的用法,请自行学习和研究
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值