zoukankan      html  css  js  c++  java
  • spring学习-AOP切面编程

    1.引入包

    --aop相关包
    spring-aop-4.0.0.RELEASE.jar
    spring-aspects-4.0.0.RELEASE.jar
    com.springsource.org.aopalliance-1.0.0.jar
    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
    --log日志相关包
    commons-logging-1.1.3.jar
    --Spring核心包
    spring-beans-4.0.0.RELEASE.jar
    spring-context-4.0.0.RELEASE.jar
    spring-core-4.0.0.RELEASE.jar
    spring-expression-4.0.0.RELEASE.jar

    2.配置文件中引入aop命名空间(红色部分),基于注解的方式需要在配置文件中添加以下代码(蓝色字体)

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop"
     6     xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
     7         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     8         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     9 
    10     <!-- 配置自动扫描的包 -->
    11     <context:component-scan base-package="com.springstudy.aop"></context:component-scan>
    12     
    13     <!-- 配置自动为匹配 aspectJ 注解的 Java 类生成代理对象 -->
    14     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    15     
    16 </beans>

    3.将横切关注点的代码抽象到切面的类中

    (1)切面首先是一个 IOC 中的 bean,即添加注解@Component

    (2)切面类也需要添加注解  @Aspect

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

    通知是标注有某种注解的简单的 Java 方法.
    
    AspectJ 支持 5 种类型的通知注解: 
        @Before: 前置通知, 在方法执行之前执行
        @After: 后置通知, 在方法执行之后执行 
        @AfterRunning: 返回通知, 在方法返回结果之后执行
        @AfterThrowing: 异常通知, 在方法抛出异常之后
        @Around: 环绕通知, 围绕着方法执行

    5.在aop的方法中要声明代理的类(下图红色字体)

    package com.springstudy.aop;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    
    @Aspect  //声明为切面类
    @Component   //配置bean实例
    public class AuthLoggingAspect {
    
        // 声明该方法是在目标方法之前执行
        @Before("execution(public int com.springstudy.aop.Auth.*(..))")
        public void befordmethod(JoinPoint jp) {
            String method = jp.getSignature().getName();
    List<Object> args = Arrays.asList(jp.getArgs());
            System.out.println(method+"Before..." + args+";"+jp.getKind());
        }
    
        public void aftermethod() {
    
        }
    
    }

     6.最典型的切入点表达式时根据方法的签名来匹配各种方法:

    2 execution * com.atguigu.spring.ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 中声明的所有方法,
      第一个 * 代表任意修饰符及任意返回值.
      第二个 * 代表任意方法. .. 匹配任意数量的参数.
      若目标类与接口与该切面在同一个包中, 可以省略包名.
    3 execution public * ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 接口的所有公有方法. 4 execution public double ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 中返回 double 类型数值的方法 5 execution public double ArithmeticCalculator.*(double, ..): 匹配第一个参数为 double 类型的方法, .. 匹配任意数量任意类型的参数 6 execution public double ArithmeticCalculator.*(double, double): 匹配参数类型为 double, double 类型的方法.

    7.让通知访问当前连接点的细节

      示例: 5 中红色字体黄色背景部分代码。类型为 JoinPoint 的参数,并通过该参数访问链接细节。

    8.其它五个方法以及通过@order(数字)指定切面优先级,即切面程序执行先后

    package com.atguigu.spring.aop;
    
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    
    /**
     * 可以使用 @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("declareJointPointExpression()") 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); } /** * 环绕通知需要携带 ProceedingJoinPoint 类型的参数. * 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法. * 且环绕通知必须有返回值, 返回值即为目标方法的返回值 */ @Around("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))") public Object aroundMethod(ProceedingJoinPoint pjd){ Object result = null; String methodName = pjd.getSignature().getName(); try { //前置通知 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs())); //执行目标方法 result = pjd.proceed(); //返回通知 System.out.println("The method " + methodName + " ends with " + result); } catch (Throwable e) { //异常通知 System.out.println("The method " + methodName + " occurs exception:" + e); throw new RuntimeException(e); } //后置通知 System.out.println("The method " + methodName + " ends"); return result; } }
    <?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-4.0.xsd">
    
        <!-- 配置 bean -->
        <bean id="arithmeticCalculator" 
            class="com.atguigu.spring.aop.xml.ArithmeticCalculatorImpl"></bean>
    
        <!-- 配置切面的 bean. -->
        <bean id="loggingAspect"
            class="com.atguigu.spring.aop.xml.LoggingAspect"></bean>
    
        <bean id="vlidationAspect"
            class="com.atguigu.spring.aop.xml.VlidationAspect"></bean>
    
        <!-- 配置 AOP -->
        <aop:config>
            <!-- 配置切点表达式 -->
            <aop:pointcut expression="execution(* com.atguigu.spring.aop.xml.ArithmeticCalculator.*(int, int))" 
                id="pointcut"/>
            <!-- 配置切面及通知 -->
            <aop:aspect ref="loggingAspect" order="2">
                <aop:before method="beforeMethod" pointcut-ref="pointcut"/>
                <aop:after method="afterMethod" pointcut-ref="pointcut"/>
                <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
                <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
                <!--  
                <aop:around method="aroundMethod" pointcut-ref="pointcut"/>
                -->
            </aop:aspect>    
            <aop:aspect ref="vlidationAspect" order="1">
                <aop:before method="validateArgs" pointcut-ref="pointcut"/>
            </aop:aspect>
        </aop:config>
    
    </beans>
  • 相关阅读:
    codeforces-1328F-Make k Equal
    codeforces-1327C-Game with Chips
    codeforces-1328E-Tree Queries
    深度学习(九):变分自编码器
    深度学习(八):概率生成模型
    深度学习(六):吉布斯采样
    深度学习(五):M-H采样
    深度学习(四):马尔科夫链蒙特卡洛采样(MCMC)
    深度学习(二):图模型的学习
    深度学习(一):概率图模型引入
  • 原文地址:https://www.cnblogs.com/yuntianblog/p/13425109.html
Copyright © 2011-2022 走看看