1. AOP 操作(准备)
1. Spring 框架一般都是基于ASpectJ 实现 AOP 操作
1. 什么是 AspectJ
AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspcetJ 和 Spring 框架一
起使用,进行 AOP 操作。
2. 基于 AspectJ 实现 AOP 操作
1. 基于 XML 配置文件实现
2. 基于注解方式实现(使用)
3. 在项目工程里面引入AOP相关依赖
pom 文件:
<?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>org.example</groupId>
<artifactId>study_spring5</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>5.3.13</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.13</version>
</dependency>
</dependencies>
</project>
4. 切入点表达式
1. 切入点表达式作用,知道对哪个类里面的哪个方法进行增强
2. 语法结构:
execution(【权限修饰符】【返回类型】【类全路径】【方法名称】【参数列表 】)
举例1:对 com.study.dao.BookDao 类里面的 add 进行增强
execution(* com.study.dao.BookDao.add(..))
举例2:对 com.study.dao.BookDao 类里面的所有方法进行增强
execution(* com.study.dao.BookDao.*(..))
举例2:对 com.study.dao 包里面所有类的所有方法进行增强
execution(* com.study.dao.*.*(..))
2. 创建类,在类里面定义方法
package com.demo.study_spring.aop.anno.aspectj;
/**
* 被增强类
*/
public class User {
public void add() {
System.out.println("这是一个添加方法。");
}
}
3. 在增强类里面,创建方法,让不同方法代表不同的通知类型
package com.demo.study_spring.aop.anno.aspectj;
/**
* 增强类
* 在增强类里面,创建方法,让不同方法代表不同的通知类型
*/
public class UserProxy {
/**
* 前置通知
*/
public void before () {
System.out.println("before ……");
}
}
4. 进行通知的配置
1. 在spring 配置文件中,开启注解扫描。
<?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 http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.demo.study_spring"></context:component-scan>
<!--开启 AspectJ 生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
2. 使用注解创建 User 和UserProxy对象。
3. 在增强类上面添加注解@Aspect。
4. 在spring 配置文件中开启生成代理对象。
5. 配置不同类型通知
1. 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置。
package com.demo.study_spring.aop.anno.aspectj;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 增强类
* 在增强类里面,创建方法,让不同方法代表不同的通知类型
*/
@Component
@Aspect
public class UserProxy {
/**
* 前置通知
* @Before 注解表示作为前置通知
*/
@Before(value = "execution(* com.demo.study_spring.aop.anno.aspectj.User.add(..))")
public void before () {
System.out.println("before ……");
}
/**
* 最终通知
*/
@After(value = "execution(* com.demo.study_spring.aop.anno.aspectj.User.add(..))")
public void after() {
System.out.println("after ……");
}
/**
* 后置通知
*/
@AfterReturning(value = "execution(* com.demo.study_spring.aop.anno.aspectj.User.add(..))")
public void afterReturning() {
System.out.println("afterReturning ……");
}
/**
* 异常通知
*/
@AfterThrowing(value = "execution(* com.demo.study_spring.aop.anno.aspectj.User.add(..))")
public void afterThrowing() {
System.out.println("afterThrowing ……");
}
/**
* 环绕通知
*/
@Around(value = "execution(* com.demo.study_spring.aop.anno.aspectj.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("around 之前……");
proceedingJoinPoint.proceed();
System.out.println("around 之后……");
}
}
运行结果:
无异常:
有异常:
6. 公共切点抽取
/**
* 相同切入点
*/
@Pointcut(value = "execution(* com.demo.study_spring.aop.anno.aspectj.User.add(..))")
public void pointDemo() {
}
/**
* 前置通知
* @Before 注解表示作为前置通知
*/
@Before(value = "pointDemo()")
public void before () {
System.out.println("before ……");
}
7. 有多个增强类,对同一个方法增强,可以设置优先级
1. 在增强类上面添加注解 @Order(数字类型值),数字类型值越小,优先级越高
package com.demo.study_spring.aop.anno.aspectj;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class PersonProxy {
/**
* 前置通知
* @Before 注解表示作为前置通知
*/
@Before(value = "execution(* com.demo.study_spring.aop.anno.aspectj.User.add(..))")
public void before () {
System.out.println("Person before ……");
}
}
8.完全使用注解开发
1. 创建配置类,不需要创建xml配置文件
package com.demo.study_spring.aop.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan(basePackages = {"com.demo"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}