本文目录

  • AspectJ 框架概述
  • 基于XML配置实现
  • 创建Spring工程
  • 创建目标接口和实现类
  • 创建切面类
  • Spring配置文件
  • 测试代码和运行结果
  • 基于注解实现
  • 目标接口和实现类
  • 切面类
  • Spring配置文件
  • 测试代码

AspectJ 框架概述

AspectJ 是基于Java的一个AOP框架,其实现方式比起Java动态代理更为简捷,使用更为方便,而且还支持注解式开发。在Spring中使用AOP开发时,一般推荐使用AspectJ的实现方式。

AspectJ中的通知类型

通知

描述

前置通知

在一个方法执行之前,执行通知。

后置通知

在一个方法执行之后,不考虑其结果,执行通知。

返回后通知

在一个方法执行之后,只有在方法成功完成时,才能执行通知

抛出异常后通知

在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。

环绕通知

在建议方法调用之前和之后,执行通知。

使用AspectJ实现AOP有两种方式:一种是基于XML的声明式AspectJ,另一种是基于注解的声明式AspectJ

基于XML配置实现

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

创建Spring工程

首先创建Spring工程:【Spring】Spring入门案例 在pom.xml中加入Spring aopAspectJ相关的包

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>aopalliance</groupId>
      <artifactId>aopalliance</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
    </dependency>

创建目标接口和实现类

public interface UserService {
    public void selectUser();
}
public class UserServiceImpl implements UserService{
    @Override
    public void selectUser() {
        System.out.println("UserServiceImpl -> selectUser");
    }
}

创建切面类

package com.lucas;


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

public class MyAspect {
    //前置通知
    public void myBefore(JoinPoint joinPoint){
        System.out.println("MyAspect ->前置通知:"+joinPoint);
        System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName());
    }
    //后置通知
    public void myAfterReturrning(JoinPoint joinPoint, Object ret){
        System.out.println("MyAspect ->前后置通知:"+joinPoint);
        System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName() +" ret =" +ret);
    }
    /*
     * 环绕通知
     * proceedingJoinPoint是JoinPoint子接口,表示可以执行目标方法
     * 1.必须是Object类型的返回值
     * 2.必须接收一个参数,类型为ProceedingJoinPoint
     * 3.必须throws Throwable
     */
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("MyAspect ->前环绕前通知");
        //执行当前目标方法
        Object obj = proceedingJoinPoint.proceed();
        System.out.println("MyAspect ->前环绕后通知");
        return obj;
    }
    //异常通知
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("MyAspect ->前异常通知:"+e.getMessage());
    }
    //最终通知
    public void myAfter(){
        System.out.println("MyAspect ->前最终通知");
    }
}

Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 目标类 -->
    <bean id="userService" class="com.lucas.UserServiceImpl"></bean>
    <!-- 切面 -->
    <bean id="myAspect" class="com.lucas.MyAspect"></bean>
    <aop:config>
        <!-- 配置切面 -->
        <aop:aspect ref="myAspect">
            <!-- 配置切入点 -->
            <aop:pointcut expression="execution(* com.lucas.*.*(..))" id="myPointCut"/>
            <!-- 前置通知 -->
            <aop:before method="myBefore" pointcut-ref="myPointCut"/>
            <!-- 后置通知      returning属性:用于设置后置通知的第二个参数的名称,类型是Object -->
            <aop:after-returning method="myAfterReturrning" pointcut-ref="myPointCut" returning="ret"/>
            <!-- 环绕通知 -->
            <aop:around method="myAround" pointcut-ref="myPointCut"/>
            <!-- 异常通知:如果没有异常,将不会执行增强
                 throwing属性:用于设置通知第二个参数的的名称、类型-->
            <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
            <!-- 最终通知 -->
            <aop:after method="myAfter" pointcut-ref="myPointCut"/>
        </aop:aspect>
    </aop:config>
</beans>

测试代码和运行结果

public class App {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.selectUser();
    }
}

spring 非aspect的aop配置_spring

基于注解实现

目标接口和实现类

public interface UserService {
    public void selectUser();
}
@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public void selectUser() {
        System.out.println("UserServiceImpl -> selectUser");
    }
}

切面类

package com.lucas;


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

@Aspect
@Component
public class MyAspect {
    @Pointcut("execution(* com.lucas.*.*(..))")
    public void myPointCut() {

    }

    //前置通知
    @Before("myPointCut()") //注解里面的值为上面的方法名
    public void myBefore(JoinPoint joinPoint){
        System.out.println("MyAspect ->前置通知:"+joinPoint);
        System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName());
    }
    //后置通知
    @AfterReturning(value = "myPointCut()", returning = "ret")
    public void myAfterReturrning(JoinPoint joinPoint, Object ret){
        System.out.println("MyAspect ->前后置通知:"+joinPoint);
        System.out.println("MyAspect ->前被植入增强处理的目标方法:"+joinPoint.getSignature().getName() +" ret =" +ret);
    }
    /*
     * 环绕通知
     * proceedingJoinPoint是JoinPoint子接口,表示可以执行目标方法
     * 1.必须是Object类型的返回值
     * 2.必须接收一个参数,类型为ProceedingJoinPoint
     * 3.必须throws Throwable
     */
    @Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("MyAspect ->前环绕前通知");
        //执行当前目标方法
        Object obj = proceedingJoinPoint.proceed();
        System.out.println("MyAspect ->前环绕后通知");
        return obj;
    }
    //异常通知
    @AfterThrowing(value = "myPointCut()", throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("MyAspect ->前异常通知:"+e.getMessage());
    }
    //最终通知
    @After("myPointCut()")
    public void myAfter(){
        System.out.println("MyAspect ->前最终通知");
    }
}

Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.lucas"/>
    <!--    开启AspectJ 注解的支持-->
    <aop:aspectj-autoproxy/>
</beans>

测试代码

public class App {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.selectUser();
    }
}

运行结果:

spring 非aspect的aop配置_xml_02