• Spring aop介绍


    最近一段时间重新学习了Spring的aop思想, 虽然在项目中使用的比较少, 但是还是这里要记录下.

    aop的使用有两种方式:  XML和注解

    1.  XML方式

    下面使用框架是SpringMVC+Mybatis+Aop, 这里只讨论Aop的作用, 其他如springmvc和mybatis的配置,这里就不给出具体代码了...

    先给出XML的配置:

        <!--  Aop(面向切面的编程, xml配置) -->    
        <bean id="aspectDemoOne" class="com.springdemo.aop.AspectDemoOne" />
        <aop:config>
            <aop:pointcut expression="execution(* com.springdemo.controller.*.*(..))" id="pointcut" /> <!-- 监听包com.springdemo.controller下所有的类和所有的方法 -->
    <!--下面的method属性对应的方法必须要在类AspectDemoOne中全部对应-->
    <aop:aspect ref="aspectDemoOne"> <!-- 前置通知 --> <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>

    下面是测试用的AspectDemoOne类:

    package com.springdemo.aop;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class AspectDemoOne {
    
        private static final Logger LOG = LogManager.getLogger(AspectDemoOne.class);
        
        /** before
         * 前置通知
         * @param joinPoint
         */
        public void beforeMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            LOG.info("beforeMethod=>this method=>" + methodName + " begin. param<" + args + ">");
        }
        
        /** after
         * 后置通知(无论方法是否发生异常都会执行, 所以访问不到方法的返回值)
         * @param joinPoint
         */
        public void afterMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            LOG.info("afterMethod=>this method=>" + methodName);
        }
        
        /** after-returning
         * 返回通知(在方法正常结束执行的代码)
         * 返回通知可以访问到方法的返回值!
         * @param joinPoint
         */
        public void afterReturnMethod(JoinPoint joinPoint, Object result){
            String methodName = joinPoint.getSignature().getName();
            LOG.info("afterReturnMethod=>this method=>" + methodName + " end.result<" + result + ">");
        }
        
        /** after-throwing
         * 异常通知(方法发生异常执行的代码)
         * 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
         * @param joinPoint
         * @param ex
         */
        public void afterThrowingMethod(JoinPoint joinPoint, Exception ex){
            String methodName = joinPoint.getSignature().getName();
            LOG.info("afterThrowingMethod=>this method=>" + methodName + " end.ex message<" + ex + ">");
        }
        
        /** around
         * 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数)
         * 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法
         * 且环绕通知必须有返回值,返回值即目标方法的返回值
         * @param point
         */
        public Object aroundMethod(ProceedingJoinPoint point){
            Object result = null;
            String methodName = point.getSignature().getName();
            try {
                //前置通知
                LOG.info("aroundMethod=>the method=>" + methodName + " start. param<" + Arrays.asList(point.getArgs()) + ">");
                //执行目标方法
                result = point.proceed();
                //返回通知
                LOG.info("aroundMethod=>the method=>" + methodName + " end. result<" + result + ">");
            } catch (Throwable e) {
                //异常通知
                LOG.info("aroundMethod=>this method=>" + methodName + " end.ex message<" + e + ">");
                throw new RuntimeException(e);
            }
            //后置通知
            LOG.info("aroundMethod=>the method=>" + methodName + " end.");
            return result;
        }
        
    }

    下面是Controller包下面的一个:

    @Controller
    @RequestMapping(value = "/author")
    public class AuthorController {
    
        private static final Logger LOG = LogManager.getLogger(AuthorController.class);
        
        @Autowired
        private AuthorService authorService;    
        
        @RequestMapping(value="/request")
        @ResponseBody
        public Author requestExample(@RequestBody Author[] authors) {
            for (Author author : authors) {
                LOG.info("name="+author.getName()+",age="+author.getAge()+",country="+author.getCountry());
            }    
            Author author = new Author();
            author.setName("authorFour");
            author.setAge(25);
            author.setCountry("Germany");
            return author;
        }    
    }

    输入URL:  http://localhost/MavenSpringMVC/author/request

    2. 注解方式

    其他的配置和上面的一样, 其中xml的配置可以删除,下面用spring的注解方式定义Aop思想:

    给出测试用的AspectDemoTwo类: 

    package com.springdemo.aop;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    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
    @Order(1)
    @Component
    public class AspectDemoTwo {
        
        private static final Logger LOG = LogManager.getLogger(AspectDemoTwo.class);
    
        /**
         * 定义一个方法,用于声明切入点表达式,方法中一般不需要添加其他代码
         * 使用@Pointcut声明切入点表达式
         * 后面的通知直接使用方法名来引用当前的切点表达式;如果是其他类使用,加上包名即可
         */
        @Pointcut("execution(public * com.springdemo.controller.*Controller.*(..))")
        public void declearJoinPointExpression() {
            
        }
        
        /**
         * before 前置通知
         * 
         * @param joinPoint
         */
        //该标签声明次方法是一个前置通知:在目标方法开始之前执行
        @Before("declearJoinPointExpression()") 
        public void beforeMethod(JoinPoint joinPoint) {
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            LOG.info("beforeMethod=>this method=>" + methodName + " begin. param<" + args + ">");
        }
    
        /**
         * after 后置通知(无论方法是否发生异常都会执行, 所以访问不到方法的返回值)
         * 
         * @param joinPoint
         */
        @After("declearJoinPointExpression()")
        public void afterMethod(JoinPoint joinPoint) {
            String methodName = joinPoint.getSignature().getName();
            LOG.info("afterMethod=>this method=>" + methodName);
        }
    
        /**
         * after-returning 返回通知(在方法正常结束执行的代码) 返回通知可以访问到方法的返回值!
         * 
         * @param joinPoint
         */
        @AfterReturning(value="declearJoinPointExpression()", returning="result")
        public void afterReturnMethod(JoinPoint joinPoint, Object result) {
            String methodName = joinPoint.getSignature().getName();
            LOG.info("afterReturnMethod=>this method=>" + methodName + " end.result<" + result + ">");
        }
    
        /**
         * after-throwing 异常通知(方法发生异常执行的代码) 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
         * 
         * @param joinPoint
         * @param ex
         */
        @AfterThrowing(value="declearJoinPointExpression()", throwing="ex")
        public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) {
            String methodName = joinPoint.getSignature().getName();
            LOG.info("afterThrowingMethod=>this method=>" + methodName + " end.ex message<" + ex + ">");
        }
    
        /**
         * around 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数)
         * 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法
         * 且环绕通知必须有返回值,返回值即目标方法的返回值
         * 
         * @param point
         */
        @Around(value="declearJoinPointExpression()")
        public Object aroundMethod(ProceedingJoinPoint point) {
            Object result = null;
            String methodName = point.getSignature().getName();
            try {
                // 前置通知
                LOG.info("aroundMethod=>the method=>" + methodName + " start. param<" + Arrays.asList(point.getArgs())
                        + ">");
                // 执行目标方法
                result = point.proceed();
                // 返回通知
                LOG.info("aroundMethod=>the method=>" + methodName + " end. result<" + result + ">");
            } catch (Throwable e) {
                // 异常通知
                LOG.info("aroundMethod=>this method=>" + methodName + " end.ex message<" + e + ">");
                throw new RuntimeException(e);
            }
            // 后置通知
            LOG.info("aroundMethod=>the method=>" + methodName + " end.");
            return result;
        }
    }

    输入URL:  http://localhost/MavenSpringMVC/author/request

    09:33:59.959 [http-nio-8080-exec-6] INFO  com.springdemo.aop.AspectDemoTwo - aroundMethod=>the method=>showAuthorByBootGrid start. param<[]>
    09:33:59.959 [http-nio-8080-exec-6] INFO  com.springdemo.aop.AspectDemoTwo - beforeMethod=>this method=>showAuthorByBootGrid begin. param<[]>
    09:34:00.005 [http-nio-8080-exec-6] INFO  com.springdemo.aop.AspectDemoTwo - aroundMethod=>the method=>showAuthorByBootGrid end. result<author/bootgrid>
    09:34:00.005 [http-nio-8080-exec-6] INFO  com.springdemo.aop.AspectDemoTwo - aroundMethod=>the method=>showAuthorByBootGrid end.
    09:34:00.005 [http-nio-8080-exec-6] INFO  com.springdemo.aop.AspectDemoTwo - afterMethod=>this method=>showAuthorByBootGrid
    09:34:00.005 [http-nio-8080-exec-6] INFO  com.springdemo.aop.AspectDemoTwo - afterReturnMethod=>this method=>showAuthorByBootGrid end.result<author/bootgrid>
    ...

      09:34:11.008 [http-nio-8080-exec-10] INFO com.springdemo.aop.AspectDemoTwo - aroundMethod=>the method=>authorBootGridTwo end. result<>
      09:34:11.008 [http-nio-8080-exec-10] INFO com.springdemo.aop.AspectDemoTwo - aroundMethod=>the method=>authorBootGridTwo end.
      09:34:11.008 [http-nio-8080-exec-10] INFO com.springdemo.aop.AspectDemoTwo - afterMethod=>this method=>authorBootGridTwo
      09:34:11.008 [http-nio-8080-exec-10] INFO com.springdemo.aop.AspectDemoTwo - afterReturnMethod=>this method=>authorBootGridTwo end.result<>

     
  • 相关阅读:
    mysql 索引
    私有变量 _变量名 、__变量名、__变量名__的区别
    python中 is 和 == 的区别
    赋值,浅拷贝,深拷贝
    Django model字段类型清单
    (转)nginx uwsgi wsgi django 这些东西究竟是什么关系
    线性结构
    复杂度_最大子列和问题(2)
    复杂度_最大子列和问题(1)
    应用实例——最大子列和问题
  • 原文地址:https://www.cnblogs.com/xumBlog/p/9105411.html
Copyright © 2020-2023  润新知