概要
在非Spring项目中实现AOP(面向切面编程)可以使用AspectJ,这是一个强大的AOP框架,独立于Spring运行。AspectJ允许你在Java程序中通过编译期或运行时插入横切关注点(cross-cutting concerns)。
下面是一个使用AspectJ在非Spring项目中实现切面的示例:
步骤:
添加依赖:
如果你使用的是Maven项目,在pom.xml
中添加AspectJ的依赖:
<dependencies>
<!-- AspectJ runtime dependency -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
<!-- AspectJ weaver dependency -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
</dependencies>
创建目标类:
创建一个需要切面的目标类
package com.example;
public class MyService {
public void performTask() {
System.out.println("Performing task...");
}
}
创建切面类:
创建一个切面类,并使用AspectJ注解来定义切点和通知。
package com.example;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyAspect {
@Before("execution(* com.example.MyService.performTask(..))")
public void beforeTask() {
System.out.println("Before performing task...");
}
@After("execution(* com.example.MyService.performTask(..))")
public void afterTask() {
System.out.println("After performing task...");
}
}
配置AspectJ:
在项目的根目录下创建一个名为aop.xml
的配置文件,用于配置AspectJ的织入。
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<aspects>
<aspect name="com.example.MyAspect"/>
</aspects>
<weaver>
<include within="com.example..*"/>
</weaver>
</aspectj>
运行代码:
创建一个主类来运行代码,并启用AspectJ的织入器
package com.example;
import org.aspectj.weaver.loadtime.WeavingURLClassLoader;
public class Main {
public static void main(String[] args) {
// Load AspectJ runtime
WeavingURLClassLoader loader = new WeavingURLClassLoader(
Main.class.getClassLoader(),
Main.class.getClassLoader().getURLs()
);
try {
// Use the AspectJ weaving class loader to load the service class
Class<?> clazz = loader.loadClass("com.example.MyService");
Object service = clazz.getDeclaredConstructor().newInstance();
clazz.getMethod("performTask").invoke(service);
} catch (Exception e) {
e.printStackTrace();
}
}
}
解释:
@Aspect
注解表示这个类是一个切面。@Before
注解表示在目标方法执行之前执行的通知。@After
注解表示在目标方法执行之后执行的通知。execution(* com.example.MyService.performTask(..))
定义了切点表达式,表示MyService
类中的performTask
方法。aop.xml
配置文件用于定义哪些切面和目标类需要被AspectJ织入。
execution表达式用法
在AspectJ中,execution
表达式可以指定一个包下的多个类和方法。你可以使用通配符来匹配多个类和方法。下面是一些常见的用法示例:
匹配一个包下的所有类的所有方法:
@Before("execution(* com.example..*.*(..))")
public void beforeAnyMethod() {
System.out.println("Before any method in com.example or its subpackages...");
}
这表示匹配com.example
包及其所有子包中的所有类的所有方法。
匹配一个包下的所有类中某些特定的方法:
@Before("execution(* com.example..*.perform*(..))")
public void beforePerformMethods() {
System.out.println("Before any method starting with 'perform' in com.example or its subpackages...");
}
这表示匹配com.example
包及其所有子包中的所有类中,以perform
开头的方法。
匹配一个包下的特定类的所有方法:
@Before("execution(* com.example.MyService.*(..))")
public void beforeMyServiceMethods() {
System.out.println("Before any method in com.example.MyService...");
}
这表示匹配com.example
包中的MyService
类的所有方法。
匹配一个包下的特定类中的特定方法:
@Before("execution(* com.example.MyService.performTask(..))")
public void beforePerformTask() {
System.out.println("Before performTask method in com.example.MyService...");
}
这表示匹配com.example
包中的MyService
类的performTask
方法。