Spring-2- AOP 切面编程

当我们需要对一个类中的方法进行功能的增强,又不想改变原方法的代码时

当我们需要保护一个类中的代码时

我们都可以使用代理模式,帮助这个类完成一些功能,这就是 AOP 切面编程

核心:切面 = 通知 + 切点

首先,需要引入 AOP 要用到的依赖

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.breeze</groupId>
    <artifactId>aspect</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <!--仓库-->
    <repositories>
        <!--spring里程碑版本的仓库-->
        <repository>
            <id>repository.spring.milestone</id>
            <name>Spring Milestone Repository</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

    <!--依赖-->
    <dependencies>
        <!--spring context-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <!--spring aspects-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

</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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
       ">
<!--包扫描-->
    <context:component-scan base-package="all"/>
<!--    要写上这一行才能开启动态代理,使用 AOP-->
    <aop:aspectj-autoproxy/>

</beans>

编写 需要被增强 的目标类方法

@Component("first")
public class First {

    //原始方法,称作目标方法
    public void origin(){
        System.out.println("我是原始方法");
    }

}

编写代理方法

@Component
@Aspect
public class Plus {

    //增强原始方法,称之为代理方法
    @Before("execution(public * all.First.*(..))")//引号中的就是切点,以切点表达式的方式找到原始方法
    public void add(){
        System.out.println("在原始方法执行前,增强了一些功能");
    }

}

@Before 就是通知,@Before 里面的参数就是切点。合起来就是切面

通知

常用通知:

@Before 目标方向执行前

 

@AfterReturning 目标方法执行后

 

@Around 前后都添加
eg:
@Around("execution(public * dao.Orcle.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {//传参连接点,固定参数
        System.out.println("----------------------------");//前环绕
        joinPoint.proceed();//执行目标,固定方法
        System.out.println("----------------------------");//后环绕
    }

 

@AfterThrowing 发生异常时添加

 

@After  放在 finally 语句块的最终通知

 

叠加通知的作用顺序:
前环绕
前置
原本的方法被执行了
后置
最终通知
后环绕

 

异常通知在最终通知之后,在异常通知之后的后环绕不会执行

切点

常用切点表达式:

一、基于方法执行的切点表达式


匹配特定方法名称
execution(* com.example.service.UserService.findUserById(..)):匹配 com.example.service.UserService 类中名为 findUserById 的方法,无论其参数类型是什么。


匹配特定包下的所有方法
execution(* com.example.service.*.*(..)):匹配 com.example.service 包下任意类的任意方法。


匹配特定返回类型的方法
execution(* com.example.service.UserService.getUser(..)) && return-type=com.example.domain.User:匹配 com.example.service.UserService 类中名为 getUser 且返回类型为 com.example.domain.User 的方法。


二、基于类的切点表达式


匹配特定类中的所有方法
within(com.example.service.UserService):匹配 com.example.service.UserService 类中的所有方法。


匹配特定包下的所有类的所有方法
within(com.example.service.*):匹配 com.example.service 包下所有类的所有方法。


三、基于注解的切点表达式


匹配带有特定注解的方法
@annotation(com.example.annotation.Loggable):匹配带有 @com.example.annotation.Loggable 注解的方法。


四、基于目标对象的切点表达式


匹配特定类型的目标对象的所有方法调用
target(com.example.domain.User):匹配目标对象为 com.example.domain.User 类型的所有方法调用。

切面叠加

当多个切面作用于一个目标方法时
可以通过 @Order(n) 排序
n 越小优先级越高
不论优先级怎样,前置通知一定在目标发放前就被执行,后置通知同理

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值