当前位置: 代码网 > it编程>编程语言>Java > Springboot如何正确使用AOP问题

Springboot如何正确使用AOP问题

2025年06月24日 Java 我要评论
​一、aop概念切面(aspect)一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是j2ee应用中一个关于横切关注点的很好的例子。在spring aop中,切面可以使用基于模式或者基于@a

​一、aop概念

切面(aspect)

  • 一个关注点的模块化,这个关注点可能会横切多个对象。
  • 事务管理是j2ee应用中一个关于横切关注点的很好的例子。
  • 在spring aop中,切面可以使用基于模式或者基于@aspect注解的方式来实现

连接点(joinpoint)

在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在springaop中,一个连接点总是表示一个方法的执行

通知(advice)

  • 在切面的某个特定的连接点上执行的动作。
  • 其中包括了around、before和after等不同类型的通知。
  • 许多aop框架(包括spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链

切入点(pointcut)

  • 匹配连接点的断言。
  • 通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时),切入点表达式如何和连接点匹配是aop的核心:spring缺省使用aspectj切入点语法

引入(intorduction)

  • 用来给一个类型声明额外的方法或属性(也被称为连接类型声明)。
  • spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。
  • 例如,你可以使用引入来使一个bean实现接口,以便简化缓存机制

目标对象(target object)

  • 被一个或者多个切面所通知的对象。也被称做被通知对象。
  • 既然spring aop是通过运行时代理实现的,这个对象永远是一个被代理对象

aop代理(aop proxy)

  • aop框架创建的对象,用来实现切面契约(例如通知方法执行等等)。
  • 在spring中,aop代理可以是jdk动态代理或者cglib代理

植入(weaving)

  • 把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。
  • 这些可以在编译时(例如使用aspectj编译器),类加载时和运行时完成。
  • spring和其他纯java aop框架一样,在运行时完成织入

二、切点表达式​

execution表达式

用于匹配方法执行的连接点,属于方法级别

语法:

execution(修饰符 返回值类型 方法名(参数)异常)

语法参数描述
修饰符可选,如public,protected,写在返回值前,任意修饰符填*号就可以
返回值类型必选,可以使用*来代表任意返回值
方法名必选,可以用*来代表任意方法
参数()代表是没有参数,(..)代表是匹配任意数量,任意类型的参数,当然也可以指定类型的参数进行匹配,如要接受一个string类型的参数,则(java.lang.string), 任意数量的string类型参数:(java.lang.string..)
异常可选,语法:throws 异常,异常是完整带包名,可以是多个,用逗号分隔

符号:

符号描述
*匹配任意字符
匹配多个包或者多个参数
+表示类及其子类

条件符:

符号描述
&&、and
||
!

案例

拦截com.gj.web包下的所有子包里的任意类的任意方法

execution(* com.gj.web..*.*(..))

拦截com.gj.web.api.test2controller下的任意方法

execution(* com.gj.web.api.test2controller.*(..))

拦截任何修饰符为public的方法

execution(public * * (..))

拦截com.gj.web下的所有子包里的以ok开头的方法

execution(* com.gj.web..*.ok*(..))

三、aop通知

在切面类中需要定义切面方法用于响应响应的目标方法,切面方法即为通知方法,通知方法需要用注解标识,aspectj支持5种类型的通知注解

注解描述
@before前置通知, 在方法执行之前执行
@after后置通知, 在方法执行之后执行
@afterreturn返回通知, 在方法返回结果之后执行
@afterthrowing异常通知, 在方法抛出异常之后
@around环绕通知,围绕方法的执行

@before

    @before("testcut()")
    public void cutprocess(joinpoint joinpoint) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop开始拦截, 当前拦截的方法名: " + method.getname());
    }

@after

    @after("testcut()")
    public void after(joinpoint joinpoint) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop执行的方法 :"+method.getname()+" 执行完了");
    }

@afterreturn:其中value表示切点方法,returning表示返回的结果放到result这个变量中

    /**
     * returning属性指定连接点方法返回的结果放置在result变量中
     * @param joinpoint 连接点
     * @param result 返回结果
     */
    @afterreturning(value = "testcut()",returning = "result")
    public void afterreturn(joinpoint joinpoint, object result) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop拦截的方法执行成功, 进入返回通知拦截, 方法名为: "+method.getname()+", 返回结果为: "+result.tostring());
    }

@afterthrowing:其中value表示切点方法,throwing表示异常放到e这个变量

    @afterthrowing(value = "testcut()", throwing = "e")
    public void afterthrow(joinpoint joinpoint, exception e) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop进入方法异常拦截, 方法名为: " + method.getname() + ", 异常信息为: " + e.getmessage());
    }

@around

    @around("testcut()")
    public object testcutaround(proceedingjoinpoint joinpoint) throws throwable {
        system.out.println("注解方式aop拦截开始进入环绕通知.......");
            object proceed = joinpoint.proceed();
            system.out.println("准备退出环绕......");
            return proceed;
    }

四、springboot中使用aop

导出依赖

        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>

在这里插入图片描述

自定义注解

package com.hl.springbootrunner.aop;

import java.lang.annotation.elementtype;
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target;


@retention(retentionpolicy.runtime)
@target(elementtype.method)
public @interface aopannotations {
}

创建切面类

package com.hl.springbootrunner.aop;

import org.aspectj.lang.joinpoint;
import org.aspectj.lang.proceedingjoinpoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.methodsignature;
import org.springframework.stereotype.component;

import java.lang.reflect.method;


@aspect
@component
public class testaspect {

    /**
     * 这里的路径填自定义注解的全路径
     */
    @pointcut("@annotation(com.hl.springbootrunner.aop.aopannotations)")
    public void testcut() {

    }

    @before("testcut()")
    public void cutprocess(joinpoint joinpoint) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop开始拦截, 当前拦截的方法名: " + method.getname());
    }

    @after("testcut()")
    public void after(joinpoint joinpoint) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop执行的方法 :" + method.getname() + " 执行完了");
    }


    @around("testcut()")
    public object testcutaround(proceedingjoinpoint joinpoint) throws throwable {
        system.out.println("注解方式aop拦截开始进入环绕通知.......");
        object proceed = joinpoint.proceed();
        system.out.println("准备退出环绕......");
        return proceed;
    }

    /**
     * returning属性指定连接点方法返回的结果放置在result变量中
     *
     * @param joinpoint 连接点
     * @param result    返回结果
     */
    @afterreturning(value = "testcut()", returning = "result")
    public void afterreturn(joinpoint joinpoint, object result) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop拦截的方法执行成功, 进入返回通知拦截, 方法名为: " + method.getname() + ", 返回结果为: " + result.tostring());
    }

    @afterthrowing(value = "testcut()", throwing = "e")
    public void afterthrow(joinpoint joinpoint, exception e) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        method method = signature.getmethod();
        system.out.println("注解方式aop进入方法异常拦截, 方法名为: " + method.getname() + ", 异常信息为: " + e.getmessage());
    }

}

自定义一个接口

@restcontroller
public class testcontroller {
 
    @getmapping("/ok")
    @aopannotations
    public string test2() {
        return "ok";
    }
 
}

测试

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com