3.SpringAOP应用实例
3.1.导入依赖
通过 spring-context
会依赖导入 spring核心包, 而spring-aspects
用于提供AspectJ的支持
xml
<!-- Spring AOP 相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.6</version>
</dependency>
<!-- 如果需要使用代理功能 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.6</version>
</dependency>
如果 用于AspectJ的运行时和编译时/加载时编织的功能 还要导入aspectjrt
和 aspectjweaver
xml
<!-- 如果使用 AspectJ 编译时或加载时织入 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
3.2.实现代码
3.2.1.业务类
增加 @Component
注册到Spring IoC容器中
java
import org.springframework.stereotype.Component;
@Component
public class GymAop {
// 业务 A : 举重训练
public String weightLifting() {
System.out.println( "进行举重训练。" );
return "感觉不断在进步!";
}
// 业务 B : 瑜伽课
public void yogaClass(String type) {
System.out.println( "参加 " + type + " [ 瑜伽课 ]。");
}
// 业务 C : 游泳训练
public void swimming() {
System.out.println( "在游泳池里游泳。");
}
}
3.2.2.切面类
java
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import javax.swing.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
@Aspect
@Component
public class AspectAop {
//前置的方法
// 功能 A : 推荐老师
@Before("execution(* com.yuan.aop.GymAop.*(..))")
public void selectMaster(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
String type = "";
if (args != null && args.length > 0) {
type = "根据您的要求: " + Arrays.toString( args );
}
System.out.println( "首先 : " + type + " 我们为您推荐一位指导老师!" );
}
//后置的方法
//功能 B : 结束提示
@After("execution(* com.yuan.aop.GymAop.*(..))")
public void overTip(JoinPoint joinPoint ){
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
System.out.println( "您在 " + new Date() + " 结束了" + method.getName() );
}
//环绕的方法
@Around("execution(* com.yuan.aop.GymAop.*(..))")
public Object doBasicProfiling(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object[] args = proceedingJoinPoint.getArgs();
// 修改 传入的参数
if (args != null && args.length > 0) {
for (int i = 0; i < args.length; i++) {
args[i] = " { " + args[i] + " } ";
}
}
//执行方法
Object obj = proceedingJoinPoint.proceed(args);
// 修改 返回值
if (obj!=null) {
obj = " { " + obj + " } ";
}
// 方法返回值
return obj;
}
}
3.2.3.测试类
java
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class TestAop {
public static void main(String[] args)
{
AnnotationConfigApplicationContext spring = new AnnotationConfigApplicationContext(TestAop.class);
GymAop bean = spring.getBean(GymAop.class);
bean.yogaClass("综合");
System.out.println("-----");
String feel = bean.weightLifting();
System.out.println("您的评价是:" + feel );
System.out.println("-----");
bean.swimming();
}
}
3.2.4.运行测试
text
首先 : 根据您的要求: [ { 综合 } ] 我们为您推荐一位指导老师!
参加 { 综合 } [ 瑜伽课 ]。
您在 Fri Aug 02 21:52:23 CST 2024 结束了yogaClass
-----
首先 : 我们为您推荐一位指导老师!
进行举重训练。
您在 Fri Aug 02 21:52:23 CST 2024 结束了weightLifting
您的评价是: { 感觉不断在进步! }
-----
首先 : 我们为您推荐一位指导老师!
在游泳池里游泳。
您在 Fri Aug 02 21:52:23 CST 2024 结束了swimming
3.3.xml配置方式
通过 xml 进行配置aop 的方式, 现在通常使用 注解式
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"
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="gymAop" class="com.yuan.aop.GymAop"></bean>
<!-- 定义切面 -->
<bean id="aspectAop" class="com.yuan.aop.AspectAop"></bean>
<aop:config>
<aop:aspect id="myaop" ref="aspectAop">
<aop:pointcut id="mycut" expression="execution(* com.yuan.aop.*.*(..))"/>
<aop:before pointcut-ref="mycut" method="selectMaster" />
<aop:after pointcut-ref="mycut" method="overTip"/>
<aop:around pointcut-ref="mycut" method="doBasicProfiling"/>
</aop:aspect>
</aop:config>
<!-- 开启AOP自动代理 -->
<aop:aspectj-autoproxy />
</beans>
3.4.SpringBoot中使用AOP
使用SpringBoot,许多相关依赖已经包含在了Spring Boot的starter依赖中
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
并且 使用 @SpringBootApplication
代替了 @Configuration
, @ComponentScan
, @EnableAspectJAutoProxy