Spring使用AspectJ

AspectJ 是一个基于 Java 语言的 AOP 框架,它扩展了 Java 语言。Spring 2.0 以后,新增了对 AspectJ 方式的支持,新版本的 Spring 框架,建议使用 AspectJ 方式开发 AOP。

使用 AspectJ 开发 AOP 通常有两种方式:

  • 基于 XML 的声明式。
  • 基于 Annotation 的声明式

基于XML的声明式

基于 XML 的声明式是指通过 Spring 配置文件的方式定义切面、切入点及声明通知,而所有的切面和通知都必须定义在 aop:config 元素中。

下面通过案例演示 Spring 中如何使用基于 XML 的声明式实现 AOP 的开发。

导入 JAR 包

使用 AspectJ 除了需要导入 Spring AOP 的 JAR 包以外,还需要导入与 AspectJ 相关的 JAR 包。

  • spring-aspects-x.x.xx.RELEASE.jar:Spring 为 AspectJ 提供的实现,在 Spring 的包中已经提供。
  • com.springsource.org.aspectj.weaver-x.x.x.RELEASE.jar:是 AspectJ 提供的规范。

切面类

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspectJ {

    /**
     * 前置通知
     *
     * @param joinPoint
     */
    public void before(JoinPoint joinPoint) {
        System.out.println("前置通知:" + joinPoint.getTarget());
        System.out.println("method:" + joinPoint.getSignature());
    }

    /**
     * 后置通知
     * @param joinPoint
     */
    public void after(JoinPoint joinPoint){
        System.out.println("后置通知:"+joinPoint.getSignature());
    }

    /**
     * 环绕通知
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕开始");
        Object proceed = proceedingJoinPoint.proceed();
        return proceed;
    }

    /**
     * 异常通知
     * @param joinPoint
     * @param e
     */
    public void exception(JoinPoint joinPoint,Throwable e){
        System.out.println("异常通知:"+e.getMessage());
    }

    /**
     * 最终通知
     */
    public void end(){
        System.out.println("最终通知");
    }

}

spring配置

 <!--目标类 -->
    <bean id="userServer" class="com.server.impl.UserServerImpl" />
    <!--切面类 -->
    <bean id="myAspectJ" class="com.aop.MyAspectJ"></bean>
    <!--AOP 编程 -->
    <aop:config>
        <!-- 配置切入点,通知最后增强哪些方法 -->
        <aop:pointcut expression="execution ( * com.server.impl.*.* (..))" id="myPointCut"/>
        <aop:aspect ref="myAspectJ">
            <!--前置通知,关联通知 Advice和切入点PointCut -->
            <aop:before method="before" pointcut-ref="myPointCut"/>
            <!--后置通知,在方法返回之后执行,就可以获得返回值returning 属性 -->
            <aop:after-returning method="after" pointcut-ref="myPointCut"/>
            <!--环绕通知 -->
            <aop:around method="around" pointcut-ref="myPointCut"/>
            <!--抛出通知:用于处理程序发生异常,可以接收当前方法产生的异常 -->
            <!-- *注意:如果程序没有异常,则不会执行增强 -->
            <!-- * throwing属性:用于设置通知第二个参数的名称,类型Throwable -->
            <aop:after-throwing method="exception" pointcut-ref="myPointCut" throwing="e"/>
            <!--最终通知:无论程序发生任何事情,都将执行 -->
            <aop:after method="end" pointcut-ref="myPointCut"/>
        </aop:aspect>
    </aop:config>

基于注解的配置

在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关的配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。

为此,AspectJ 框架为 AOP 开发提供了另一种开发方式——基于 Annotation 的声明式。AspectJ 允许使用注解定义切面、切入点和增强处理,而 Spring 框架则可以识别并根据这些注解生成 AOP 代理。

名称 说明
@Aspect 用于定义一个切面。
@Before 用于定义前置通知,相当于 BeforeAdvice。
@AfterReturning 用于定义后置通知,相当于 AfterReturningAdvice。
@Around 用于定义环绕通知,相当于MethodInterceptor。
@AfterThrowing 用于定义抛出通知,相当于ThrowAdvice。
@After 用于定义最终final通知,不管是否异常,该通知都会执行。
@DeclareParents 用于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。

切面类


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAspectJ {

    // 用于取代:<aop:pointcut expression="execution(*com.mengma.dao..*.*(..))" id="myPointCut"/>
    // 要求:方法必须是private,没有值,名称自定义,没有参数
    @Pointcut(value="execution ( * com.server.impl.*.*(..))")
    private void myPointCut() {
    }

    /**
     * 前置通知
     *
     * @param joinPoint
     */
    @Before("myPointCut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("前置通知:" + joinPoint.getTarget());
        System.out.println("method:" + joinPoint.getSignature());
    }

    /**
     * 后置通知
     * @param joinPoint
     */
    @AfterReturning(value = "myPointCut()")
    public void after(JoinPoint joinPoint){
        System.out.println("后置通知:"+joinPoint.getSignature());
    }

    /**
     * 环绕通知
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "myPointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕开始");
        Object proceed = proceedingJoinPoint.proceed();
        return proceed;
    }

    /**
     * 异常通知
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "myPointCut()",throwing = "e")
    public void exception(JoinPoint joinPoint,Throwable e){
        System.out.println("异常通知:"+e.getMessage());
    }

    /**
     * 最终通知
     */
    @After(value = "myPointCut()")
    public void end(){
        System.out.println("最终通知");
    }

}

spring配置

    <!-- 使切面开启自动代理 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
posted @ 2020-05-13 20:53  continued258  阅读(521)  评论(0)    收藏  举报