Spring_2023_11_22_1 AspectJ(面向切面编程框架)

发布时间 2023-11-22 11:51:05作者: Kbaor

AspectJ(面向切面编程框架)

Aspectj是一个基于java的、面向切面的AOP框架。Spring2.0之后增加了对Aspectj切点表达式的支持。而实际开发中一般都使用Aspectj方式来实现AOP。所以还要导入Aspectj相关jar包。

aspectJ 包含通知类型:

  1. before:前置通知
  2. afterReturning:后置通知(可以获取返回值)
  3. afterThrowing:抛出异常的通知
  4. after最终通知
  5. around:环绕通知

案例驱动形式:xml形式

引入依赖 aspectj 框架

        <!-- 
		Spring 基础包括 :
		Spring-core/Spring-beans/Spring-app/Spring-expression
         -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.20</version>
        </dependency>
        <!--添加lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>
	    <!--aop框架: aspectj-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>

目标类:UserService/UserServiceImpl

package com.bboy.service.impl;

import com.bboy.service.UserService;

/**
 * @类描述:
 * @作者:秦帅
 * @时间:2023/11/22 0022 10:35:49
 */
public class UserServiceImpl implements UserService {
    @Override
    public int addUser() {
        System.out.println("================>addUser");
        return 100;
    }

    @Override
    public void updateUser() {
        System.out.println("================>updateUser");
    }
    @Override
    public int deleteUserById(int id) {
        System.out.println("================>deleteUserById");
        return 200;
    }
}

切面类:MyAspectj

切面类(包含了多种通知:前置通知、后置通知、后置的返回通知、异常的通知等)

import org.aspectj.lang.JoinPoint;
JoinPoint包不要导错

package com.bboy.aspect;


import org.aspectj.lang.JoinPoint;

/**
 * @类描述:
 * 切面类(包含了多种通知:前置通知、后置通知、后置的返回通知、异常的通知等)
 * @作者:秦帅
 * @时间:2023/11/22 0022 10:38:18
 */
public class MyAspectJ {
    /*
         前置通知
         joinpoint  :连接点
                此对象可以包含目标类当前执行方法的所有信息,如方法名,方法传入的参数
     */
public void myBefore(JoinPoint joinPoint){
    //- : 获取方法名
    String method_name = joinPoint.getSignature().getName();
    //- : 获取方法的参数
    Object[] objs = joinPoint.getArgs();
    for (Object obj:objs){
        System.out.println("参数====》"+obj);
    }
    System.out.println(method_name+"========>myBefore");


}
    /*
         后置通知
     */
    public void myAfter(JoinPoint joinPoint){
        //- : 获取方法名
        String method_name = joinPoint.getSignature().getName();
        //- : 获取方法的参数
        Object[] objs = joinPoint.getArgs();
        for (Object obj:objs){
            System.out.println("参数====》"+obj);
        }
        System.out.println(method_name+"========>myAfter");
    }
    /*
         执行后获取返回的通知  通知
         参数中 :  Object res  方法的返回值
     */
    public void myAfterReturning(JoinPoint joinPoint ,Object res){
        //- : 获取方法名
        String method_name = joinPoint.getSignature().getName();
        //- : 获取方法的参数
        Object[] objs = joinPoint.getArgs();
        for (Object obj:objs){
            System.out.println("参数====》"+obj);
        }
        System.out.println(method_name+"========>myAfterReturning:"+res);
    }
    /*
        执行后抛出异常的通知
        参数中 : Throwable e     抛出的异常
     */
    public void myAfterThrowing(JoinPoint joinPoint , Throwable e){
        //- : 获取方法名
        String method_name = joinPoint.getSignature().getName();
        //- : 获取方法的参数
        Object[] objs = joinPoint.getArgs();
        for (Object obj:objs){
            System.out.println("参数====》"+obj);
        }
        System.out.println(method_name+"========>myAfterThrowing:"+e.getMessage());
    }


}

核心配置文件中的注册

1. 引入aop命名空间

image

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>

2. 目标类的注册

    <!--1.创建目标类-->
    <bean id="userService" class="com.bboy.service.impl.UserServiceImpl"/>

3. 切面类的注册

  <!--2.创建切面类-->
    <bean id="myLogAspect" class="com.bboy.aspect.MyAspectJ"/>

4. Aop配置

aop编写:配置
            1.aop:aspect   :  声明切面类,从而获取切面类的通知
            2.aop:pointcut :  切入点(目标类对应的方法)
            3.aop:before   :  前置通知
                    3.1     method  指代前面切面类中的方法(切面类中哪个方法是前置方法)
                    3.2     pointcut-ref  切入点的引入
            4.aop:after    :  后置通知
                    4.1     method  指代前面切面类中的方法(切面类中哪个方法是后置方法)
                    4.2     pointcut-ref  切入点的引入
            5.aop:after-returning    :  执行完毕之后返回值的通知
                    5.1     method  指代前面切面类中的方法
                    5.2     pointcut-ref  切入点的引入
                    5.3     returning : 返回值的参数名
                            注意: returning的返回值内容,必须和切面类中对应方法的参数名一致
            6.aop:after-throwing    :  执行完毕后抛出的异常的通知
                    6.1     method  指代前面切面类中的方法
                    6.2     pointcut-ref  切入点的引入
                    6.3     throwing  : 异常的信息
                            注意:   throwing的返回值内容,必须和切面类中对性的参数名一致
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--1.创建目标类-->
    <bean id="userService" class="com.bboy.service.impl.UserServiceImpl"/>
    <!--2.创建切面类-->
    <bean id="myAspectJ" class="com.bboy.aspect.MyAspectJ"/>

    <!--3.aop编写:配置
            1.aop:aspect   :  声明切面类,从而获取切面类的通知
            2.aop:pointcut :  切入点(目标类对应的方法)
            3.aop:before   :  前置通知
                    3.1     method  指代前面切面类中的方法(切面类中哪个方法是前置方法)
                    3.2     pointcut-ref  切入点的引入
            4.aop:after    :  后置通知
                    4.1     method  指代前面切面类中的方法(切面类中哪个方法是后置方法)
                    4.2     pointcut-ref  切入点的引入
            5.aop:after-returning    :  执行完毕之后返回值的通知
                    5.1     method  指代前面切面类中的方法
                    5.2     pointcut-ref  切入点的引入
                    5.3     returning : 返回值的参数名
                            注意: returning的返回值内容,必须和切面类中对应方法的参数名一致
            6.aop:after-throwing    :  执行完毕后抛出的异常的通知
                    6.1     method  指代前面切面类中的方法
                    6.2     pointcut-ref  切入点的引入
                    6.3     throwing  : 异常的信息
                            注意:   throwing的返回值内容,必须和切面类中对性的参数名一致
    -->
    <aop:config proxy-target-class="true">
        <aop:aspect ref="myAspectJ">
            <!--
            2.aop:pointcut :  切入点(目标类对应的方法)
            -->
            <aop:pointcut id="mypointcut" expression="execution(* com.bboy.service.impl.UserServiceImpl.*(..))"/>
            <!--
            3.aop:before   :  前置通知
            3.1     method  指代前面切面类中的方法(切面类中哪个方法是前置方法)
            3.2     pointcut-ref  切入点的引入
            -->
            <aop:before method="myBefore" pointcut-ref="mypointcut"/>
            <!--
            4.aop:after    :  后置通知
            4.1     method  指代前面切面类中的方法(切面类中哪个方法是后置方法)
            4.2     pointcut-ref  切入点的引入
            -->
            <aop:after method="myAfter" pointcut-ref="mypointcut"/>
            <!--
            5.aop:after-returning    :  执行完毕之后返回值的通知
                    5.1     method  指代前面切面类中的方法
                    5.2     pointcut-ref  切入点的引入
                    5.3     returning : 返回值的参数名
                            注意: returning的返回值内容,必须和切面类中对应方法的参数名一致
            -->
            <aop:after-returning method="myAfterReturning" pointcut-ref="mypointcut" returning="res"/>
            <!--
            6.aop:after-throwing    :  执行完毕后抛出的异常的通知
                    6.1     method  指代前面切面类中的方法
                    6.2     pointcut-ref  切入点的引入
                    6.3     throwing  : 异常的信息
                            注意:   throwing的返回值内容,必须和切面类中对性的参数名一致
            -->
            <aop:after-throwing method="myAfterThrowing" pointcut-ref="mypointcut" throwing="e"/>

        </aop:aspect>



    </aop:config>
</beans>

测试类

package com.bboy.demo;

import com.bboy.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @类描述:
 * @作者:秦帅
 * @时间:2023/11/22 0022 11:18:32
 */
public class Demo {
    public static void main(String[] args) {
        //-:获取  spring 容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //-: 从容器中获取Bean对象
        UserService userService = (UserService) context.getBean("userService");
        userService.updateUser();
        userService.deleteUserById(2);
        userService.addUser();
    }
    }

运行结果

image