SpringBoot集成AOP的代码示例

 更新时间:2024年09月08日 08:23:27   作者:HBLOG  
AOP是一种编程范式,它旨在将横切关注点(cross-cutting concerns)从应用程序的业务逻辑中分离出来,横切关注点是那些在多个模块中重复出现的功能,如日志记录、性能监控、事务管理、安全控制等,本文介绍了Spring Boot如何集成AOP,需要的朋友可以参考下

1.什么是AOP?

AOP(Aspect Oriented Programming,面向切面编程)是一种编程范式,它旨在将横切关注点(cross-cutting concerns)从应用程序的业务逻辑中分离出来。横切关注点是那些在多个模块中重复出现的功能,如日志记录、性能监控、事务管理、安全控制等。AOP允许开发者将这些关注点模块化,并在不影响应用程序主要功能的情况下,将它们编织到应用程序的各个点上。

AOP的关键概念

  • 切面(Aspect):封装了横切关注点的模块。它描述了要执行的附加行为以及该行为应该被应用到哪些连接点上。
  • 连接点(Joinpoint):程序执行过程中的某个点,如方法调用或异常抛出。
  • 通知(Advice):切面在特定的连接点上执行的动作,如“before”、“after”、“around”等。
  • 切入点(Pointcut):匹配连接点的表达式,定义了切面的哪个部分会被应用到哪些连接点上。
  • 目标对象(Target Object):被一个或多个切面所通知的对象。
  • 代理(Proxy):由AOP框架创建的对象,用来拦截目标对象上的方法调用。

AOP的实现方式

AOP可以通过以下几种方式实现:

  • 基于代理的AOP:
    • JDK动态代理:适用于实现接口的情况,利用反射机制生成代理类。
    • CGLIB:使用字节码技术生成子类,适用于未实现接口的情况。
  • 基于字节码操作的AOP:
    • AspectJ:在编译期或运行期通过修改字节码来实现切面的编织,可以更细粒度地控制切面的织入。
  • 声明式AOP:
    • Spring AOP:使用XML配置或注解(如@Aspect@Before@After@Around等)来定义切面和切入点,然后在运行时通过动态代理实现切面的编织。

实现AOP的关键技术

  • 动态代理:在运行时动态创建代理对象,代理对象在调用目标方法前后可以执行额外的操作。
  • 字节码操作库:如ASM、ByteBuddy等,用于生成或修改字节码,实现在类的加载之前或运行时修改类的行为。
  • 元数据驱动:使用注解或XML配置来定义切面、切入点和通知,便于配置和管理AOP的规则。

AOP的主要优点是能够减少业务逻辑中的重复代码,提高代码的模块化程度,使得关注点更加集中,同时也提高了代码的可维护性和可读性。在实际应用中,AOP经常被用于企业级应用开发,如在Spring框架中广泛使用。

2.代码工程

实验目标

采用@aspect注解来实现aop

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>aspect</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
       
    </dependencies>
</project>

controller

package com.et.aspect.controller;

import com.et.aspect.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class HelloWorldController {
    @Autowired
    TestService testService;


    @RequestMapping("/hello")
    public Map<String, Object> showHelloWorld(){
        Map<String, Object> map = new HashMap<>();
        String str=  testService.sayHello("liming");
        map.put("msg",str);
        return map;
    }
}

service

package com.et.aspect.service;

public interface TestService {
    public String sayHello(String name) ;
}

package com.et.aspect.service.impl;

import com.et.aspect.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author liuhaihua
 * @version 1.0
 * @ClassName TestServiceImpl
 * @Description todo
 * @date 2024/09/05/ 9:21
 */
@Service
@Slf4j
public class TestServiceImpl implements TestService {
    @Override
    public String sayHello(String name) {
        String  sss="hello,"+name;
        log.info(sss);
        return sss;
    }
}

aspect

  • @Aspect:作用是把当前类标识为一个切面供容器读取

  • @Pointcut:定义切入点,Pointcut是植入Advice的触发条件。 每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。 可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。 因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。

  • @Around:环绕增强,相当于MethodInterceptor(方法拦截器)

  • @AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行

  • @Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有

  • @AfterThrowing:异常抛出增强,相当于ThrowsAdvice(异常通知)

  • @After: final增强,不管是抛出异常或者正常退出都会执行

@Pointcut("execution(* com.et.aspect.service..*.*(..))")
public void aopPoint() {

}

@Before("aopPoint()")
public void doBefore(JoinPoint point) throws Throwable {
    log.info("before ....");
}
@After("aopPoint()")
public void doAfter(JoinPoint point) throws Throwable {
    log.info("after ....");
}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

3.测试

  • 启动Spring Boot应用程序

  • 访问http://127.0.0.1:8088/hello

  • 查看日志如下

    2024-09-05 21:52:12.926 INFO 51009 --- [nio-8088-exec-1] com.et.aspect.aspect.TaskAspect : before .... 2024-09-05 21:52:12.939 INFO 51009 --- [nio-8088-exec-1] c.e.aspect.service.impl.TestServiceImpl : hello,liming 2024-09-05 21:52:12.939 INFO 51009 --- [nio-8088-exec-1] com.et.aspect.aspect.TaskAspect : after ....

以上就是Spring Boot集成AOP的代码示例的详细内容,更多关于Spring Boot集成AOP的资料请关注脚本之家其它相关文章!

相关文章

  • Map 使用 Lambda 的 forEach 实现跳出循环操作

    Map 使用 Lambda 的 forEach 实现跳出循环操作

    这篇文章主要介绍了Map 使用 Lambda 的 forEach 实现跳出循环操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • 关于Spring多数据源TransactionManager冲突的解决方案

    关于Spring多数据源TransactionManager冲突的解决方案

    这篇文章主要介绍了关于Spring多数据源TransactionManager冲突的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Spring测试基本的控制器实战示例

    Spring测试基本的控制器实战示例

    这篇文章主要为大家介绍了Spring测试基本的控制器实战示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • MybatisPlus+Postgresql整合的几个坑及解决

    MybatisPlus+Postgresql整合的几个坑及解决

    这篇文章主要介绍了MybatisPlus+Postgresql整合的几个坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 浅谈一下SpringBoot中的异步任务

    浅谈一下SpringBoot中的异步任务

    这篇文章主要介绍了浅谈一下SpringBoot中的异步任务,SpringBoot 中的异步任务主要是指在 SpringBoot 中使用异步线程完成处理任务,在 SpringBoot 中使用异步线程非常简单,只需要两个注解就可以搞定,需要的朋友可以参考下
    2023-10-10
  • JAVA如何按字节截取字符串

    JAVA如何按字节截取字符串

    这篇文章主要介绍了JAVA如何按字节截取字符串,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Springcloud eureka搭建高可用集群过程图解

    Springcloud eureka搭建高可用集群过程图解

    这篇文章主要介绍了Springcloud eureka搭建高可用集群过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Spring简明分析Bean作用域

    Spring简明分析Bean作用域

    scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对象进入其 相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象,这篇文章主要介绍了Spring中的Bean作用域,需要的朋友可以参考下
    2022-07-07
  • Mybatis 在 insert 插入操作后返回主键 id的操作方法

    Mybatis 在 insert 插入操作后返回主键 id的操作方法

    这篇文章主要介绍了Mybatis 在 insert 插入操作后返回主键 id的操作方法,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • SpringCloud实现Redis在各个微服务的Session共享问题

    SpringCloud实现Redis在各个微服务的Session共享问题

    Redis是运行在内存中,查取速度很快。本文重点给大家介绍SpringCloud实现Redis在各个微服务的Session共享,感兴趣的朋友一起看看吧
    2018-08-08

最新评论