AOP 操作
- AOP 操作(准备)
- 1. Spring 框架一般是基于 AspectJ 实现 AOP 操作
- (1)什么是 AspectJ
- 2. 基于 AspectJ 实现 AOP 操作
- 3. 在项目工程里面引入 AOP 先关的依赖
- 4. 切入点表达式
- 举例1:对 com.fairykunkun.dao.UserDao 类里面的 add 进行增强
- 举例2:对 com.fairykunkun.dao.UserDao 类里面的所有方法进行增强
- 举例3:对 com.fairykunkun.dao 包里面的所有类的所有方法进行增强
- AOP 操作( Aspect 注解)
- 1. 创建一个类,在类里面定义方法
- 2. 创建增强类(编写增强逻辑)
- (1)在增强类里面,创建方法,让不同的方法代表不同的通知类型
- 3. 进行通知的一个配置
- (1)在 Spring 的配置文件中开启注解的扫描
- (2)使用注解创建 User 和 UserProxy 对象
- (3)在增强类上面添加注解 @Aspect
- (4)在 Spring 配置文件中开启生成代理对象
- 4. 配置不同类型的通知
- (1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
- 5. 测试
- 6. 总结
- 7. 公共(相同)切入点抽取
- 8. 多个增强类对我们的同一个方法进行增强,设置增强类的优先级
- 9. 完全使用注解开发
- AOP 操作( AspectJ 配置文件)
- 1. 创建两个类,增强类和被增强类,创建方法
- 2. 在 Spring 配置文件中创建两个类对象
- 3. 在 Spring 配置文件中配置切入点
AOP 操作(准备)
1. Spring 框架一般是基于 AspectJ 实现 AOP 操作
(1)什么是 AspectJ
AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spring 框架一起使用,进行 AOP 操作
2. 基于 AspectJ 实现 AOP 操作
(1)基于 xml 配置文件实现
(2)基于注解的方式实现
3. 在项目工程里面引入 AOP 先关的依赖
<!--aop相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.9.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.23.1</version>
</dependency>
4. 切入点表达式
(1)切入点表达式的作用:知道对哪个类里面的那个方法进行增强
(2)语法结构
execution([权限修饰符][返回类型][全类名][方法名称]([参数列表]))
举例1:对 com.fairykunkun.dao.UserDao 类里面的 add 进行增强
execution(*com.fairykunkun.dao.UserDao.add(..))
举例2:对 com.fairykunkun.dao.UserDao 类里面的所有方法进行增强
execution(*com.fairykunkun.dao.UserDao.*(..))
举例3:对 com.fairykunkun.dao 包里面的所有类的所有方法进行增强
execution(*com.fairykunkun.dao.*.*(..))
AOP 操作( Aspect 注解)
1. 创建一个类,在类里面定义方法
package com.fairykunkun.aopanno;
// 被增强的类
public class User {
public void add ( ) {
System.out.println ( "add ..." );
}
}
2. 创建增强类(编写增强逻辑)
(1)在增强类里面,创建方法,让不同的方法代表不同的通知类型
package com.fairykunkun.aopanno;
// 增强的类
public class UserProxy {
public void before ( ) {
// 前置通知
System.out.println ( "before ..." );
}
}
3. 进行通知的一个配置
(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.fairykunkun.aopanno"></context:component-scan>
</beans>
(2)使用注解创建 User 和 UserProxy 对象
package com.fairykunkun.aopanno;
import org.springframework.stereotype.Component;
// 被增强的类
@Component
public class User {
public void add ( ) {
System.out.println ( "add ..." );
}
}
package com.fairykunkun.aopanno;
import org.springframework.stereotype.Component;
// 增强的类
@Component
public class UserProxy {
// 前置通知
public void before ( ) {
System.out.println ( "before ..." );
}
}
(3)在增强类上面添加注解 @Aspect
package com.fairykunkun.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
// 增强的类
@Component
@Aspect // 生成代理对象
public class UserProxy {
// 前置通知
public void before ( ) {
System.out.println ( "before ..." );
}
}
(4)在 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.fairykunkun.aopanno"></context:component-scan>
<!-- 开启 Aspect生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
4. 配置不同类型的通知
(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
package com.fairykunkun.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
// 增强的类
@Component
@Aspect // 生成代理对象
public class UserProxy {
// 前置通知
// @Before 注解表示作为前置通知
// * 表示可以返回任意值
@Before ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void before ( ) {
System.out.println ( "before ..." );
}
}
5. 测试
package com.fairykunkun;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.fairykunkun.aopanno.User;
public class TestAop {
@Test
public void testAopAno ( ) {
ApplicationContext context =
new ClassPathXmlApplicationContext ( "bean11.xml" );
User user = context.getBean ( "user" , User.class );
user.add ( );
}
}
- 继续完善增强类的方法
package com.fairykunkun.aopanno;
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.fairykunkun.aopanno.User.add(..))" )
public void before ( ) {
System.out.println ( "before ..." );
}
@AfterThrowing ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void afterThrowing ( ) {
System.out.println ( "afterThrowing......" );
}
@After ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void after ( ) {
System.out.println ( "after......" );
}
// 环绕通知
@Around ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void around ( ProceedingJoinPoint proceedingJoinPoint ) throws Throwable {
System.out.println ( "环绕之前......" );
// 被增强的方法执行
proceedingJoinPoint.proceed ( );
System.out.println ( "环绕之后......" );
}
}
- 再看一下测试结果
package com.fairykunkun.aopanno;
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.fairykunkun.aopanno.User.add(..))" )
public void before ( ) {
System.out.println ( "before ..." );
}
@AfterThrowing ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void afterThrowing ( ) {
System.out.println ( "afterThrowing......" );
}
@AfterReturning ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void afterReturning ( ) {
System.out.println ( "afterReturning......" );
}
@After ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void after ( ) {
System.out.println ( "after......" );
}
// 环绕通知
@Around ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void around ( ProceedingJoinPoint proceedingJoinPoint ) throws Throwable {
System.out.println ( "环绕之前......" );
// 被增强的方法执行
proceedingJoinPoint.proceed ( );
System.out.println ( "环绕之后......" );
}
}
- 看一下实验结果
- 在 User 的 add 方法中模拟一个异常
package com.fairykunkun.aopanno;
import org.springframework.stereotype.Component;
// 被增强的类
@Component
public class User {
public void add ( ) {
int i=10/0;
System.out.println ( "add ..." );
}
}
- 测试
6. 总结
- @Before(前置通知)
- @AfterReturning(后置通知,返回通知)
- @After(最终通知)
- @Around(环绕通知)
- @AfterThrowing(异常通知)
7. 公共(相同)切入点抽取
package com.fairykunkun.aopanno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
// 增强的类
@Component
@Aspect // 生成代理对象
public class UserProxy {
// 相同切入点抽取
@Pointcut ( value = "execution(* com.fairykunkun.aopanno.User.add(..))" )
public void pointdemo ( ) {
}
// 前置通知
// @Before 注解表示作为前置通知
// * 表示可以返回任意值
@Before ( value = "pointdemo()" )
public void before ( ) {
System.out.println ( "before ..." );
}
@AfterThrowing ( value = "pointdemo()" )
public void afterThrowing ( ) {
System.out.println ( "afterThrowing......" );
}
@AfterReturning ( value = "pointdemo()" )
public void afterReturning ( ) {
System.out.println ( "afterReturning......" );
}
@After ( value = "pointdemo()" )
public void after ( ) {
System.out.println ( "after......" );
}
// 环绕通知
@Around ( value = "pointdemo()" )
public void around ( ProceedingJoinPoint proceedingJoinPoint ) throws Throwable {
System.out.println ( "环绕之前......" );
// 被增强的方法执行
proceedingJoinPoint.proceed ( );
System.out.println ( "环绕之后......" );
}
}
- 把之前做的那个异常去掉,然后再做测试
8. 多个增强类对我们的同一个方法进行增强,设置增强类的优先级
package com.fairykunkun.aopanno;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class PersonProxy {
// 前置通知
@Before (value = "execution(* com.fairykunkun.aopanno.User.add(..))")
public void before() {
System.out.println ("Person Before......" );
}
}
(1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高
package com.fairykunkun.aopanno;
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 (value = "execution(* com.fairykunkun.aopanno.User.add(..))")
public void before() {
System.out.println ("Person Before......" );
}
}
- 测试
9. 完全使用注解开发
(1)创建配置类,不需要创建 xml 配置文件
package com.fairykunkun.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan ( basePackages = { "com.fairykunkun" } )
@EnableAspectJAutoProxy ( proxyTargetClass = true )
public class AopConfig {
}
AOP 操作( AspectJ 配置文件)
1. 创建两个类,增强类和被增强类,创建方法
package com.fairykunkun.aopxml;
public class Book {
public void buy ( ) {
System.out.println ( "buy" );
}
}
package com.fairykunkun.aopxml;
public class BookProxy {
public void before ( ) {
System.out.println ( "before......" );
}
}
2. 在 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: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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- 创建对象 -->
<bean id = "book" class = "com.fairykunkun.aopxml.Book"></bean>
<bean id = "bookProxy" class = "com.fairykunkun.aopxml.BookProxy"></bean>
</beans>
3. 在 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: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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- 创建对象 -->
<bean id = "book" class = "com.fairykunkun.aopxml.Book"></bean>
<bean id = "bookProxy" class = "com.fairykunkun.aopxml.BookProxy"></bean>
<!-- 配置 aop 增强 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut id = "p" expression = "execution(* com.fairykunkun.aopxml.Book.buy(..))"/>
<!-- 配置切面 -->
<aop:aspect ref = "bookProxy">
<!-- 增强作用在具体的方法上 -->
<aop:before method = "before" pointcut-ref = "p"/>
</aop:aspect>
</aop:config>
</beans>
- 测试
package com.fairykunkun;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.fairykunkun.aopxml.Book;
public class TestAop {
@Test
public void testAopXml ( ) {
ApplicationContext context =
new ClassPathXmlApplicationContext ( "bean12.xml" );
Book book = context.getBean ( "book" , Book.class );
book.buy ( );
}
}