zoukankan      html  css  js  c++  java
  • Spring AOP

    Spring AOP 可以使用XML 配置方式和注解方式

    而AOP的类型有如下三种

    1. 显示声明前置后置AOP方法

    2. 环绕AOP方法

    3. 使用接口扩展已知类

    以下是各种类型示例

    applicationContext.xml示例

    <!-- 带参AOP示例 -->
            <aop:aspect ref="idInterceptor" >
                <!-- 在切入点设置方法参数类型和参数名 -->
                <aop:pointcut id="interceptId" expression="
                    execution(* com.xxx.service.UserServiceImpl.buyTicket(int))
                    and args(userId)" />
                <!-- 接货参数的参数名 -->
                <aop:before method="setUserId" pointcut-ref="interceptId" arg-names="userId" />
            </aop:aspect>
    
            <!-- 切面实现新接口AOP示例 -->
            <aop:aspect>
                <!-- 声明需要扩展的类和需要实现的接口,+表示衍生类 -->
                <!-- implement-interface是切点类需要实现的接口 -->
                <!-- default-impl是接口的实现方法 -->
                 <!--types-matching如果写的是具体接口实现类,就不能转成那个类了,只能写这个接口 -->
                <aop:declare-parents types-matching="com.xxx.service.UserServiceIntf+"
                     implement-interface="com.xxx.aop.ExtraAopIntf"
                     default-impl="com.xxx.aop.ExtraAop" />
    
                <!-- 实现类也可以使用bean id代替,此时需要将实现类注册为bean -->
                <aop:declare-parents types-matching="com.xxx.service.UserServiceImplImpl+"
                                     implement-interface="com.xxx.aop.ExtraAopIntff"
                                     delegate-ref="extraAop" />
            </aop:aspect>
        <!-- 自动注册 -->
        <context:component-scan base-package="com.xxx" >
            <!-- 排除由ServletDispatcher管理的controller包和MyBatis管理的mapper包 -->
            <!--<context:exclude-filter type="regex" expression=".controller.*" />-->
            <!--<context:exclude-filter type="regex" expression=".mapper.*" />-->
            <context:include-filter type="regex" expression=".bean.*" />
            <context:include-filter type="regex" expression=".service.*" />
            <!-- aop中切面包含的bean似乎只能通过显示的bean注册
            不能自动注册,所以此处不写,直接移动到xxxBeans.xml文件 -->
        </context:component-scan>

    dispatcher-servlet.xml示例

        <!-- 开启Controller自动注册,必须写在这个文件里 -->
        <context:component-scan base-package="com.xxx.controller" />
    
     <!-- Web层AOP配置 -->
        <aop:config>
            <!-- 声明一个切面 -->
            <aop:aspect ref="logger">
                <!-- 声明一个切点 -->
                <!-- expression的含义: * 表示返回值为任意类型 .. 表示参数为任意类型 -->
                <aop:pointcut id="listAllLog" expression="
                    execution(* com.xxx.controller.UserController.listAll(..))" />
                <!-- 声明前置通知 -->
                <aop:before method="beforeLog" pointcut-ref="listAllLog" />
                <!-- 声明返回后置通知 -->
                <aop:after-returning method="successLog" pointcut-ref="listAllLog" />
                <!-- 声明异常后置通知 -->
                <aop:after-throwing method="failLog" pointcut-ref="listAllLog" />
            </aop:aspect>
    
            <!-- 环绕通知示例 -->
            <aop:aspect ref="security" >
                <aop:pointcut id="listAllSecurity" expression="
                    execution(* com.xxx.controller.UserController.listAll(..))" />
                <aop:around method="securityCheck" pointcut-ref="listAllSecurity" />
            </aop:aspect>
        </aop:config>

    使用注解的方式AOP

    受限开启自动注册注解AOPbean

        <!-- 开启自动AOP代理bean功能,它可以自动生成使用了@Aspect的通知类的代理类,类似于自动注册 -->
        <aop:aspectj-autoproxy />

    1. 显示限定调用注解类

    package com.xxx.aop;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-7-19
     * Time: 下午3:42
     * To change this template use File | Settings | File Templates.
     */
    
    import org.aspectj.lang.annotation.*;
    
    /**
     * 注解AOP测试
     */
    @Aspect
    public class Logger {
        @Pointcut(
            "execution(* com.xxx.controller.UserController.listAll())")
        // 此处的listAll无意义,相当于<aop:pointcut>里的id
        public void listAll() {}
    
        @Before("listAll()")
        public void beforeLog() {
            System.out.println("Prepared to log");
        }
    
        @AfterReturning("listAll()")
        public void successLog() {
            System.out.println("Log successfully");
        }
    
        @AfterThrowing("listAll()")
        public void failLog() {
            System.out.println("Log fail");
        }
    }

    2. 环绕通知

    package com.xxx.aop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-7-19
     * Time: 下午6:42
     * To change this template use File | Settings | File Templates.
     */
    
    /**
     * 注解环绕通知示例
     */
    @Aspect
    public class Security {
        @Pointcut(
                "execution(* com.xxx.controller.UserController.listAll())")
        // 此处的listAll无意义,相当于<aop:pointcut>里的id
        public void listAll() {}
    
        // 使用环绕通知
        @Around("listAll()")
        public void securityCheck(ProceedingJoinPoint joinPoint) {
            try {
                System.out.println("Prepared to Security check");
                joinPoint.proceed();
                System.out.println("Security check finished");
            } catch (Throwable throwable) {
                System.out.println("Security system error");
            }
        }
    }

    3.带参AOP

    package com.xxx.aop;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-7-19
     * Time: 下午10:36
     * To change this template use File | Settings | File Templates.
     */
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    /**
     * 演示带参AOP方法
     */
    @Aspect
    public class IdInterceptor {
        @Pointcut(
            "execution(* com.xxx.service.UserServiceIntf." +
            "buyTicket(int)) && args(userId))")
        public void buyTicket(int userId){};
    
        private int userId;
    
        public int getUserId() {
            return userId;
        }
    
        @Before("buyTicket(userId)")
        public void setUserId(int userId) {
            this.userId = userId;
        }
    }

    4. 接口扩展AOP

    package com.xxx.aop;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-7-20
     * Time: 下午1:41
     * To change this template use File | Settings | File Templates.
     */
    
    public interface ExtraAopIntf {
        void extraFunc();
    }
    
    package com.xxx.aop;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-7-20
     * Time: 下午1:42
     * To change this template use File | Settings | File Templates.
     */
    /**
     * 基于注解的实现新接口AOP切面
     */
    @Aspect
    public class ExtraAop implements ExtraAopIntf {
        @Override
        public void extraFunc() {
            System.out.println("Execute extra aop func");
        }
    }
    
    
    package com.xxx.aop;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    
    /**
     * Created with IntelliJ IDEA.
     * User: zhenwei.liu
     * Date: 13-7-20
     * Time: 下午5:01
     * To change this template use File | Settings | File Templates.
     */
    @Aspect
    public class ExtraAopAspect {
        /**
         * value 表示需要被扩展的bean类型
         * defaultImp 表示实现扩展的类
         * static 属性成员extraAopInft代表扩展的类型
         */
        @DeclareParents(
                value = "com.xxx.service.UserServiceIntf+",
                defaultImpl = ExtraAop.class
        )
        public static ExtraAopIntf extraAopIntf;
    }
  • 相关阅读:
    TortoiseGit 合并主分支代码.pull request
    MVC EF 修改某些值
    MVC 提交表单
    MVC 统计之 自定义 列表
    MVC 起始页修改 区域
    asp.net C# MVC DropDownList
    asp.net C# MVC 提交表单后清空表单
    Python 线程启动的四种方式
    Git 命令的学习
    Node.js v10.1.0 Documentation
  • 原文地址:https://www.cnblogs.com/zemliu/p/3207910.html
Copyright © 2011-2022 走看看