ITPub博客

首页 > 数据库 > 数据库开发技术 > Spring Boot如何集成AOP?

Spring Boot如何集成AOP?

原创 数据库开发技术 作者:hblog 时间:2024-09-07 20:26:29 0 删除 编辑

1.什么是AOP?

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

AOP的关键概念

  • 切面(Aspect):封装了横切关注点的模块。它描述了要执行的附加行为以及该行为应该被应用到哪些连接点上。

  • 连接点(Joinpoint):程序执行过程中的某个点,如方法调用或异常抛出。

  • 通知(Advice):切面在特定的连接点上执行的动作,如“before”、“after”、“around”等。

  • 切入点(Pointcut):匹配连接点的表达式,定义了切面的哪个部分会被应用到哪些连接点上。

  • 目标对象(Target Object):被一个或多个切面所通知的对象。

  • 代理(Proxy):由AOP框架创建的对象,用来拦截目标对象上的方法调用。

AOP的实现方式

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

  1. 基于代理的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;
    @RestControllerpublic 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@Slf4jpublic 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增强,不管是抛出异常或者正常退出都会执行

    package com.et.aspect.aspect;
    import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;
    @Aspect@Component@Slf4jpublic class TaskAspect {


    @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 ...."); }}

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

    代码仓库

    • https://github.com/Harries/springboot-demo(aspect)

    3.测试

    1. 启动Spring Boot应用程序

    2. 访问http://127.0.0.1:8088/hello

    3. 查看日志如下

    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,liming2024-09-05 21:52:12.939 INFO 51009 --- [nio-8088-exec-1] com.et.aspect.aspect.TaskAspect : after ....

    4.引用

    • https://docs.spring.io/spring-framework/reference/core/aop.html

    • http://www.liuhaihua.cn/archives/711301.html

    原文作者:HBLOG;如有侵权,请联系管理员删除。

    请登录后发表评论 登录
    全部评论

    注册时间:2022-05-04

    • 博文量
      210
    • 访问量
      111727