zoukankan      html  css  js  c++  java
  • Spring框架学习笔记(8)——AspectJ实现AOP

    使用代理对象实现AOP虽然可以满足需求,但是较为复杂,而Spring提供一种简单的实现AOP的方法AspectJ

    同样的计算器的DEMO

    首先配置applicationContext.xml

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>
        
    <!-- 配置自动为匹配 aspectJ 注解的 Java 类生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

     

    在计算器实现类ArithmeticCalculatorImpl上加注解@Component("arithmeticCalculator")

    创建类LoggingAspect作为计算器的一个切面,添加注解@Aspect和@Component

    LoggingAspect里添加一个方法beforeMethod即前置通知

    /**
     * 在 com.atguigu.spring.aop.ArithmeticCalculator 接口的每一个实现类的每一个方法开始之前执行一段代码
     */
    @Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))") public void beforeMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); Object [] args = joinPoint.getArgs(); System.out.println("The method " + methodName + " begins with " + Arrays.asList(args)); }

    切入点表达式

    execution(public <返回类型>int <接口方法,*为通配符(..)为参数,代表这个接口的每个实现类的每个方法>com.atguigu.spring.aop.ArithmeticCalculator.*(..))
    这里也可以指定某一个方法,比如add(..)
    切入点表达式还可以使用|| && !这些连接符
    execution(public * *.add(..))||execution(public * *.div(..))


    连接点参数类型

    JoinPoint可以访问更多细节比如方法名和参数
    对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint . 它是 JoinPoint 的子接口, 允许控制何时执行, 是否执行连接点.


    完成这些就可以运行main方法

        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");
        
        System.out.println(arithmeticCalculator.getClass().getName());
        
        int result = arithmeticCalculator.add(1, 2);
        System.out.println("result:" + result);
        
        result = arithmeticCalculator.div(1000, 10);
        System.out.println("result:" + result);
    
    
    

    类似的可以添加其他通知

    AspectJ 支持 5 种类型的通知注解:

    @Before: 前置通知, 在方法执行之前执行

    @After: 后置通知, 在方法执行之后执行

    @AfterRunning: 返回通知, 在方法返回结果之后执行

    @AfterThrowing: 异常通知, 在方法抛出异常之后

    @Around: 环绕通知, 围绕着方法执行

    日志切面详细代码

    /**
     * 可以使用 @Order 注解指定切面的优先级, 值越小优先级越高
     */
    @Order(2)
    @Aspect
    @Component
    public class LoggingAspect {
        
        /**
         * 定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码. 
         * 使用 @Pointcut 来声明切入点表达式. 
         * 后面的其他通知直接使用方法名来引用当前的切入点表达式. 
         */
        @Pointcut("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")
        public void declareJointPointExpression(){}
        
        /**
         * 在 com.atguigu.spring.aop.ArithmeticCalculator 接口的每一个实现类的每一个方法开始之前执行一段代码
         */
        @Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")
        public void beforeMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            Object [] args = joinPoint.getArgs();
            
            System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
        }
        
        /**
         * 在方法执行之后执行的代码. 无论该方法是否出现异常
         */
        @After("declareJointPointExpression()")
        public void afterMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " ends");
        }
        
        /**
         * 在方法法正常结束受执行的代码
         * 返回通知是可以访问到方法的返回值的!
         */
        @AfterReturning(value="declareJointPointExpression()",
                returning="result")
        public void afterReturning(JoinPoint joinPoint, Object result){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " ends with " + result);
        }
        
        /**
         * 在目标方法出现异常时会执行的代码.
         * 可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码
         */
        @AfterThrowing(value="declareJointPointExpression()",
                throwing="e")
        public void afterThrowing(JoinPoint joinPoint, Exception e){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " occurs excetion:" + e);
        }
    }

    环绕通知示例代码

    Spring4.0支持@order注解当有多个切面的时候可以使用@order来为切面的执行顺序进行排序

    比如添加一个验证切面添加注解@Order(1),日志切面添加注解@Order(2)

     
     
  • 相关阅读:
    JVM,反射与动态代理
    11款实用的一句话网站设计代码
    Winform TextBox中只能输入数字的几种常用方法(C#)
    列表checkbox全选
    函数调用约定
    vs编译后在本机能运行,在别的机器上运行提示runtime Error的问题
    学习地形编程(一)
    Ogre中动态三维鼠标的实现
    讲讲volatile的作用
    绕任意轴旋转的推导
  • 原文地址:https://www.cnblogs.com/huangjian2/p/6274110.html
Copyright © 2011-2022 走看看