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;
}
原文地址:https://www.cnblogs.com/zemliu/p/3207910.html