Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。
一、实现方式
Spring AOP:基于代理机制,使用JDK动态代理和CGLIB(Code Generation Library)在运行时生成代理对象,通过代理对象拦截方法调用并执行切面逻辑。这种方式对Spring管理的Bean生效,支持灵活的切点表达式,但对非Spring Bean的方法调用无效。
AspectJ AOP:使用编译时织入或类加载时织入,通过修改目标类的字节码来实现切面逻辑。这种方式不依赖于代理,可以应用于任何Java对象,支持更丰富的切面逻辑,但需要额外的配置和复杂性。
二、灵活性
Spring AOP:主要对Spring管理的Bean生效,支持方法级别的切面,切点表达式相对简单。
AspectJ AOP:不仅限于Spring管理的Bean,可以应用于所有Java对象,支持类级别和方法级别的切面,切点表达式更为丰富和复杂。
三、依赖性
Spring AOP:依赖于Spring框架,与Spring容器紧密集成,适用于Spring项目。
AspectJ AOP:作为一个独立的框架,不依赖于Spring或其他容器,适用于任何Java项目。
四、性能
Spring AOP:动态代理的方式相对轻量,性能较好,但对于大规模或频繁的切面逻辑可能会有性能损耗。
AspectJ AOP:通过编译时或类加载时织入,性能较高,但配置和使用更为复杂。
五、使用场景
Spring AOP:适用于轻量级的AOP需求,如日志记录、事务管理等,对Spring框架集成友好。
AspectJ AOP:适用于复杂的AOP需求,如系统架构中需要对各个层次的组件进行切面,或对非Spring Bean的对象进行切面等。
总体而言,选择Spring AOP还是AspectJ AOP取决于具体的项目需求和场景,以及对AOP实现方式的偏好。
这两者总的来说
Spring AOP 是spring支持的面向切面AOP 编程。AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
AspectJ AOP示例:
使用AspectJ AOP,我们可以不需要Spring容器,并且切面表达式更为灵活。首先,创建一个普通的Java项目。
然后,创建一个目标类MyService。
public class MyService {
public void doSomething() {
System.out.println("do something...");
}
}
接下来,我们创建一个切面类LogAspect:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class LogAspect {
@Before("myPointcut()")
public void logBefore() {
long startTime = System.currentTimeMillis();
System.out.println("method execution started at: " + startTime);
}
@Pointcut("execution(* com.service.MyService.*(..))")
public void myPointcut() {
}
}
在AspectJ AOP中,我们使用@Aspect注解来标记一个切面,并使用@Before注解来定义在方法执行前执行的通知。
最后,创建一个应用程序主类:
public class MainApp {
public static void main(String[] args) {
MyService myService = new MyService();
myService.doSomething();
}
}
当运行MainApp类时,LogAspect中的logBefore方法将在MyService的doSomething方法执行之前被调用,记录方法的开始时间。
注意,在AspectJ AOP示例中,我们无需Spring容器,而且切面表达式更为灵活。
目标对比
SpringAOP 不是一个完备的AOP 方案。
AspectJ是最首创的AOP技术,用来提供全面的AOP方案。
织入方式
AspectJ 使用了三种不同类型的织入方式:
Compile-time weaving:编译期织入。编译器将切面和应用的源代码编译在一个字节码文件中。
Post-compile weaving:编译后织入。也称为二进制织入。将已有的字节码文件与切面编制在一起。
Load-time weaving:加载时织入。与编译后织入一样,只是织入时间会推迟到类加载到jvm时。
Spring AOP使用运行时织入(runtime weaving)
在运行时织入,是使用目标对象的代理对象织入的。
SpringAOP 是基于动态代理的实现AOP,这意味着实现目标对象的切面会创建一个代理类(两种代理模式)。而AspectJ在程序运行期是不会做任何事情的,因为类和切面是直接编译在一起的,这种方式称为静态代理。
性能上来说,编译期织入要比运行期织入快很多。因此aspectJ 的运行速度要快于springAOP。
连接点 Joinpoints
Spring AOP 只支持方法执行连接点,而ASpectJ 还支持方法调用,构造方法调用,属性引用,静态初始化以及其他切面的通知等作为连接点, 功能相当强大。