• springmvc配置AOP的两种方式


    https://www.cnblogs.com/qinglangyijiu/p/8425653.html

    spingmvc配置AOP有两种方式,一种是利用注解的方式配置,另一种是XML配置实现。

    应用注解的方式配置:

    先在maven中引入AOP用到的依赖

    复制代码
    <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.1.RELEASE</version>
        </dependency>
        <!-- aop aspect注解导包-->
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>1.8.6</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.9</version>
        </dependency>
    复制代码

    然后在springmvc的配置文件中加入AOP的配置,即扫描AOP的包以及让AOP生效

    <!-- AOP 注解方式 ;定义Aspect -->
        <!-- 激活组件扫描功能,在包"com.example.aop及其子包下面自动扫描通过注解配置的组件-->
        <context:component-scan base-package="com.example.aop"/>
        <!-- 启动AspectJ支持   只对扫描过的bean有效-->
        <aop:aspectj-autoproxy proxy-target-class="true" />

    然后加入AOP逻辑处理类

    复制代码
    package com.example.aop;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    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;
    
    @Aspect    //该标签把LoggerAspect类声明为一个切面
    @Order(1)  //设置切面的优先级:如果有多个切面,可通过设置优先级控制切面的执行顺序(数值越小,优先级越高)
    @Component //该标签把LoggerAspect类放到IOC容器中
    public class LoggerAspect {
    
        /**
         * 定义一个方法,用于声明切入点表达式,方法中一般不需要添加其他代码
         * 使用@Pointcut声明切入点表达式
         * 后面的通知直接使用方法名来引用当前的切点表达式;如果是其他类使用,加上包名即可
         */
        @Pointcut("execution(public * com.example.controller.*Controller.*(..))")
        public void declearJoinPointExpression(){}
    
        /**
         * 前置通知
         * @param joinPoint
         */
        @Before("declearJoinPointExpression()") //该标签声明次方法是一个前置通知:在目标方法开始之前执行
        public void beforMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            System.out.println("this method "+methodName+" begin. param<"+ args+">");
        }
        /**
         * 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值)
         * @param joinPoint
         */
        @After("declearJoinPointExpression()")
        public void afterMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("this method "+methodName+" end.");
        }
        /**
         * 返回通知(在方法正常结束执行的代码)
         * 返回通知可以访问到方法的返回值!
         * @param joinPoint
         */
        @AfterReturning(value="declearJoinPointExpression()",returning="result")
        public void afterReturnMethod(JoinPoint joinPoint,Object result){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("this method "+methodName+" end.result<"+result+">");
        }
        /**
         * 异常通知(方法发生异常执行的代码)
         * 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
         * @param joinPoint
         * @param ex
         */
        @AfterThrowing(value="declearJoinPointExpression()",throwing="ex")
        public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("this method "+methodName+" end.ex message<"+ex+">");
        }
        /**
         * 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数)
         * 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法
         * 且环绕通知必须有返回值,返回值即目标方法的返回值
         * @param point
         */
        @Around(value="declearJoinPointExpression()")
        public Object aroundMethod(ProceedingJoinPoint point){
    
            Object result = null;
            String methodName = point.getSignature().getName();
            try {
                //前置通知
                System.out.println("The method "+ methodName+" start. param<"+ Arrays.asList(point.getArgs())+">");
                //执行目标方法
                result = point.proceed();
                //返回通知
                System.out.println("The method "+ methodName+" end. result<"+ result+">");
            } catch (Throwable e) {
                //异常通知
                System.out.println("this method "+methodName+" end.ex message<"+e+">");
                throw new RuntimeException(e);
            }
            //后置通知
            System.out.println("The method "+ methodName+" end.");
            return result;
        }
    }
    复制代码

    在类上加上注解Aspect声明这个类是一个切面,加上component注解加入IOC容器中。Order注解是优先级,如果只有一个切面类可以不用。注解pointcut是声明注解的作用范围。execution(public * com.example.controller.*Controller.*(..))我这里用的execution表达式,代表作用com.example.controller包下所有以Controller结尾类的所有Public方法。@pointcut所描述的方法里面通常不需要内容。切面通知包含:

    前置通知(@Before,在执行方法之前,参数为JoinPoint)

    后置通知(@After,无论方法抛不抛异常都会执行,所以获取不到方法的返回值。参数为JoinPoint)

    返回通知(@AfterReturning,在方法正常结束后执行,可以获取到方法的返回值。参数为JoinPoint和result(Object))

    异常通知(@AfterThrowing,在方法抛出异常时执行,可以获取到异常对象,且可以指定在出现特定异常时执行的代码,参数为JoinPoint何Exception)

    环绕通知(@Around,环绕通知需要携带的类型为ProceedingJoinPoint类型的参数, 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法,且环绕通知必须有返回值,返回值即目标方法的返回值)

    应用XML方式配置

    依赖的话,应该不用加入AOP注解的依赖。先定义一个类,作为切面类。

    复制代码
    package com.example.aop;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.springframework.stereotype.Component;
    
    @Component //该标签把LoggerAspect类放到IOC容器中
    public class SysAspect {
    
        /**
         * 前置通知
         * @param joinPoint
         */
        public void beforMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            System.out.println("this method "+methodName+" begin. param<"+ args+">");
        }
        /**
         * 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值)
         * @param joinPoint
         */
        public void afterMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("this method "+methodName+" end.");
        }
        /**
         * 返回通知(在方法正常结束执行的代码)
         * 返回通知可以访问到方法的返回值!
         * @param joinPoint
         */
        public void afterReturnMethod(JoinPoint joinPoint,Object result){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("this method "+methodName+" end.result<"+result+">");
        }
        /**
         * 异常通知(方法发生异常执行的代码)
         * 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
         * @param joinPoint
         * @param ex
         */
        public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("this method "+methodName+" end.ex message<"+ex+">");
        }
        /**
         * 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数)
         * 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法
         * 且环绕通知必须有返回值,返回值即目标方法的返回值
         * @param point
         */
        public Object aroundMethod(ProceedingJoinPoint point){
    
            Object result = null;
            String methodName = point.getSignature().getName();
            try {
                //前置通知
                System.out.println("The method "+ methodName+" start. param<"+ Arrays.asList(point.getArgs())+">");
                //执行目标方法
                result = point.proceed();
                //返回通知
                System.out.println("The method "+ methodName+" end. result<"+ result+">");
            } catch (Throwable e) {
                //异常通知
                System.out.println("this method "+methodName+" end.ex message<"+e+">");
                throw new RuntimeException(e);
            }
            //后置通知
            System.out.println("The method "+ methodName+" end.");
            return result;
        }
    }
    复制代码

    可以看到,这个类除了没有@Aspect以及相关切面的注解外,跟正常的AOP切面类没有差别。如果声明其让其为一个切面。需要我们在xml文件中手动配置。

    复制代码
    <!-- 配置切面的Bean -->
        <bean id="sysAspect" class="com.example.aop.SysAspect"/>
        <!-- 配置AOP -->
        <aop:config>
            <!-- 配置切点表达式  -->
            <aop:pointcut id="pointcut" expression="execution(public * com.example.controller.*Controller.*(..))"/>
            <!-- 配置切面及配置 -->
            <aop:aspect order="3" ref="sysAspect">
                <!-- 前置通知 -->
                <aop:before method="beforMethod"  pointcut-ref="pointcut" />
                <!-- 后置通知 -->
                <aop:after method="afterMethod"  pointcut-ref="pointcut"/>
                <!-- 返回通知 -->
                <aop:after-returning method="afterReturnMethod" pointcut-ref="pointcut" returning="result"/>
                <!-- 异常通知 -->
                <aop:after-throwing method="afterThrowingMethod" pointcut-ref="pointcut" throwing="ex"/>
                <aop:around method="aroundMethod" pointcut-ref="pointcut"/>
            </aop:aspect>
        </aop:config>
    复制代码

    定义的切面bean就是我们自定义的切面类,然后配置AOP(<aop:config>)。先定义切面范围pointcut。余下的就是制定aop的切面类、优先级然后再详细配置切面的通知。这样就跟注解的方式产生的效果一致了。

  • 相关阅读:
    搞明白这八个问题,Linux系统就好学多了
    Fedora 25 Alpha版本今天发布啦
    Linux新手应掌握的10个基本命令
    PC-BSD 换名 TrueOS
    JPA+Springboot实现分页效果
    陈亮
    押尾光太郎
    岸部真明
    面试必备-网络的七层协议
    JavaScript中的快速排序
  • 原文地址:https://www.cnblogs.com/zhoading/p/12204648.html
Copyright © 2020-2023  润新知