欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用AspectJ实现AOP

程序员文章站 2022-05-24 12:27:43
...

AOP专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在JavaEE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP已经成为一种非常常用的解决方案。

在学习SpringAOP之前,我们先来简单看看AspectJ。

AspectJ是一个基于Java语言的AOP框架,提供了强大的AOP功能,其他很多AOP框架都借鉴或采纳其中的一些思想。由于Spring3.0的AOP与AspectJ进行了很好的集成,因此掌握AspectJ是学习SpringAOP的基础。

AspectJ主要包括两个部分:

部分 描述
第一部分

定义了如何表达、定义AOP编程中的语法规范,通过这套规范,我们可以方便地用AOP来解决Java语言中存在的交叉关注点问题。

另一部分 工具部分,包括编译器、调试工具等。
package com.ant;

public class Hello{
	
	public static void main(String[] args){
		Hello hello = new Hello();
		hello.sayHello();
	}
	
	public void sayHello(){
		System.out.println("Hello AspectJ!");
	} 
}
package com.ant;

public aspect TxAspect{

	void around():call(void Hello.sayHello()){
		System.out.println("Transaction start...");
		proceed();
		System.out.println("Transaction end...");
	}
}

使用AspectJ实现AOP

package com.ant;

public aspect LogAspect{
	
	pointcut logPointcut():execution(void Hello.sayHello());
	
	after():logPointcut(){
		System.out.println("log...");
	}
}

使用AspectJ实现AOP

我们利用javap反编译生成的Hello.class,可以发现它不是由Hello.java编译得到的,该Hello.class文件内新增了很多内容------这表明AspectJ在编译时已经增强了Hello.class的功能,因此AspectJ通常被称为编译时增强的AOP框架。

Compiled from "Hello.java"
public class com.ant.Hello {
  public com.ant.Hello();
    Code:
       0: aload_0       
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class com/ant/Hello
       3: dup           
       4: invokespecial #17                 // Method "<init>":()V
       7: astore_1      
       8: aload_1       
       9: astore_2      
      10: aload_2       
      11: invokestatic  #56                 // Method com/ant/TxAspect.aspectOf:()Lcom/ant/TxAspect;
      14: aconst_null   
      15: invokestatic  #60                 // Method sayHello_aroundBody1$advice:(Lcom/ant/Hello;Lcom/ant/TxAspect;Lorg/aspectj/runtime/internal/AroundClosure;)V
      18: return        

  public void sayHello();
    Code:
       0: getstatic     #24                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #30                 // String Hello AspectJ!
       5: invokevirtual #32                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: goto          20
      11: astore_1      
      12: invokestatic  #67                 // Method com/ant/LogAspect.aspectOf:()Lcom/ant/LogAspect;
      15: invokevirtual #70                 // Method com/ant/LogAspect.ajc$after$com_ant_LogAspect$1$9fd5dd97:()V
      18: aload_1       
      19: athrow        
      20: invokestatic  #67                 // Method com/ant/LogAspect.aspectOf:()Lcom/ant/LogAspect;
      23: invokevirtual #70                 // Method com/ant/LogAspect.ajc$after$com_ant_LogAspect$1$9fd5dd97:()V
      26: return        
    Exception table:
       from    to  target type
           0    11    11   Class java/lang/Throwable

  private static final void sayHello_aroundBody0(com.ant.Hello);
    Code:
       0: aload_0       
       1: invokevirtual #18                 // Method sayHello:()V
       4: return        

  private static final void sayHello_aroundBody1$advice(com.ant.Hello, com.ant.TxAspect, org.aspectj.runtime.internal.AroundClosure);
    Code:
       0: getstatic     #24                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #44                 // String Transaction start...
       5: invokevirtual #32                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: aload_2       
       9: astore_3      
      10: aload_0       
      11: invokestatic  #62                 // Method sayHello_aroundBody0:(Lcom/ant/Hello;)V
      14: getstatic     #24                 // Field java/lang/System.out:Ljava/io/PrintStream;
      17: ldc           #52                 // String Transaction end...
      19: invokevirtual #32                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      22: return        
}

与AspectJ相对的还有另外一种AOP框架,它们不需要在编译时对目标类进行增强,而是运行时生成目标类的代理类,该代理类要么与目标类实现相同的接口,要么是目标类的子类------总之,代理类都对目标类进行了增强处理,前者是JDK动态代理的处理策略,后者是cglib代理的处理策略。SpringAOP以创建动态代理的方式来生成代理类,底层既可使用JDK动态代理,也可采用cglib代理。

转载于:https://my.oschina.net/u/2914561/blog/777808