JavaSpring-AOP详解(Maven导入 深入浅出)

本文详细介绍如何使用Spring AOP实现方法增强,包括配置依赖、创建切入点、应用通知等关键步骤,并解析AOP术语及其应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在CSDN上看了很多关于配置AOP的文章,不是很复杂就是省略了很多步骤。本文用最简单并且最清晰的方法从导入依赖到AOP底层原理。逐步讲解SpringAOP的相关操作帮你快速了解AOP。 

目录

通过Maven仓库导入相关依赖

AOP(开始)

AOP术语

AOP五种通知

AOP相同切入点的抽取

有多个增强类对同一个同一个方法进行增强

通过Maven仓库导入相关依赖

文件结构:

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>GarsonSpring</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <spring.version>5.2.2.RELEASE</spring.version>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>9</source>
                    <target>9</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <name>GarsonSpring</name>

    <dependencies>
<!--测试需要的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>compile</scope>
        </dependency>
<!--SpringAOP-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>

    </dependencies>

</project>

Spring.xml:

<?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
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy />
    <!--开启注解扫描-->
    <context:component-scan base-package="SpringAOP.aop" />
</beans>

User:

package SpringAOP.aop;

import org.springframework.stereotype.Component;

@Component
public class User {
    public void add(){
        System.out.println("add...");
    }
}

UserProxy:

package SpringAOP.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect//生成代理对象
public class UserProxy {

    //前置通知
    @Before("execution(* SpringAOP.aop.*.*(..))")
    public void before(){
        System.out.println("before");
    }

}

AOP(开始)

成功完成本模块中的<实际操作>就代表可以正确运行AOP

1、 切入点表达式:

(1)知道对哪个类里面的哪个方法进行增强

(2)语法结构:

        此表达式表示对SpringAOP.aop包中的所有类的所有方法进行增强

          @Pointcut("execution(* SpringAOP.aop.*.*(..))")

        此表达式表示对SpringAOP.aop包中User类的add方法进行增强

          @Pointcut("execution(* SpringAOP.aop.User.add(..))")

2、进行通知的配置

(1) 在spring配置文件中,开启注解扫描

            ·在“通过Maven仓库导入相关依赖”中就已设置

(2)使用注解创建User和UserProxy对象

           ·即在类前面增加@Component

           ·使得可以使用xml中的注解创建对象

(3)在增强类(UserProxy)上面添加注解@Aspect

           ·如果有AspectJ就生成代理对象

(4)在Spring配置文件中开启生成代理对象

           ·在“通过Maven仓库导入相关依赖”中就已设置

<实际操作(代码复制可直接运行)>

类:

package SpringAOP.aop;

import org.springframework.stereotype.Component;

@Component
public class User {
    public void add(){
        System.out.println("add...");
    }
}

增强类:

package SpringAOP.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect//生成代理对象
public class UserProxy {

    //前置通知
    @Before("execution(* SpringAOP.aop.*.*(..))")
    public void before(){
        System.out.println("before");
    }

}

测试方法:

    @Test
    public void test1() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User user = applicationContext.getBean("user", User.class);
        user.add();
    }

测试结果:

总结:

AOP其实就是在一个固定的类外面套一层代理类,在代理类可以增加你希望的方法及操作但却不需要改变原始类。达到了解耦合的目的,更利于维护。

AOP术语

在结束上面的AOP引入,相信我们已经对AOP有一些了解了

接下来我们再了解更深入一点的AOP术语

1、横切关注点

从每个方法中抽取出来的同一类非核心业务。在同一个项目中,我们可以使用多个横切关注点对相关方法进行多个不同方面的增强。

这个概念不是语法层面天然存在的,而是根据附加功能的逻辑上的需要:有十个附加功能,就有十个横切关注点。

2、通知

每一个横切关注点上要做的事情都需要写一个方法来实现,这样的方法就叫通知方法。

· 前置通知:在被代理的目标方法前执行

· 返回通知:在被代理的目标方法成功结束后执行(寿终正寝)

· 异常通知:在被代理的目标方法异常结束后执行(死于非命)

· 后置通知:在被代理的目标方法最终结束后执行(盖棺定论)

· 环绕通知:使用try...catch...finally结构围绕整个被代理的目标方法,包括上面四种通知对· 应的所有位置

3、切面

封装通知的类

4、目标

被代理的目标对象

5、代理

向目标对象应用通知之后创建的代理对象。

6、连接点

向目标对象应用通知之后创建的代理对象。

7、切入点

定位连接点的方式。

每个类的方法中都包含多个连接点,所以连接点是类中客观存在的事物(从逻辑上说)。

如果把连接点看作数据库中的记录,那么切入点就是查询记录的 SQL 语句。Spring 的 AOP 技术可以通过切入点定位到特定的连接点。切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。

 AOP五种通知

上文我们使用到了@Before。有了在指定方法前执行,

那就肯定有在后面、在异常抛出后、前后都执行...等,下面我们将介绍AOP的五种通知

@Before, 在 join point 前被执行的 advice. 虽然@Before是在 join point 前被执行, 但是它并不能够阻止 join point 的执行, 除非发生了异常。

@AfterReturning, 在一个 join point 正常返回后执行的 advice

@AfterThrowing, 当一个 join point 抛出异常后执行的 advice
@After( = final), 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice
@Around, 在 join point 前和 joint point 退出后都执行

AOP相同切入点的抽取

(很多人这一点讲的很复杂)

我用流程来说明:其实@Before的对象现在是pointCutDemo()方法了,但是pointCutDemo指向的是SpringAOP.aop.User类中的add()方法。所以Before还是会在add()方法之前执行

一句话:before() 在 pointCutDemo = User.add() 方法前执行

    @Pointcut("execution(* SpringAOP.aop.User.add(..))")
    public void pointCutDemo(){}


    //前置通知
    @Before("pointCutDemo()")
    public void before(){
        System.out.println("before");
    }

有多个增强类对同一个同一个方法进行增强

设置增强类优先级

就是有很多男生约一个女生吃饭,那女生就要给男生们排序号啦

有多个代理类想代理,我们给代理类设置一个优先级

在增强类上面添加注解@Order(数字类型值),数字类型值越小等级越高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值