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

使用 AspectJ 实现 AOP

程序员文章站 2022-05-24 12:28:07
...

AspectJ 下载地址:点击这里

下载完成之后,得到一个 *.jar 文件,进入该文件所在的路径,执行命令:

java -jar *.jar

这样会出现一个由 java 编写的安装程序,过程都很简单,安装结束。

其中安装路径包含 /bin/、/lib/ 等文件夹,需要配置 CLASSPATH、PATH 环境变量。


模拟业务方法:

public class UserService {
    public int login(String username, String password) {
        System.out.println("执行 login() 方法");
        return 1;
    }
}

主程序模拟调用业务方法:

public class AspectJTest {

    public static void main(String[] args) {
        UserService userService = new UserService();
        userService.login("root", "root");
    }
}

考虑这种情况:假设客户要求在执行所有业务方法之前先执行权限检查,如果使用传统的编程方式,开发者必须先定义一个权限检查的方法,然后编辑每个业务方法,向其中增加调用权限检查的方法,容易引发新的错误,而且维护成本大。


下面使用 AspectJ 的 AOP 支持,添加如下 Java 类:

public aspect AuthAspect {
	
	before() : execution(* *.*(..)) {
		System.out.println("模拟进行权限检查...");
	}
}

ps:这并不是一个 Java 类,需要使用到上面 aspectj 安装路径下 /bin/ajc.bat 脚本来编译,这个脚本是 javac.exe 的增强版。


接着,使用 AspectJ 目录下 /bin/ajc.bat 编译:

ajc *.java -encoding UTF-8

ps:所有文件都需要使用 ajc 来进行编译。如果你只是将 aspect 文件使用 ajc 编译,其他使用 javac 来编译是没有效过的;甚至需要使用 *.java 一起进行编译,单独使用 ajc 编译会产生奇怪的错误。


执行如下命令:

java AspectJTest

控制台输出:

模拟进行权限检查...
模拟进行权限检查...
执行 login() 方法

ps:执行了两次权限检查是因为使用了 *,使切面方法自己也算作切入点。


如果需要在执行所有业务方法之后增加记录日志的功能,添加如下类:

public aspect LogAspect {
	/* 声明切入点,简化切入点表达式 */
	pointcut logPointcut() : execution(* *.*(..));
	
	after() : logPointcut() {
		System.out.println("模拟记录日志...");
	}
}

编译之后,控制台输出:

模拟进行权限检查...
模拟进行权限检查...
执行 login() 方法
模拟记录日志...
模拟记录日志...

如果需要在业务组件的所有业务方法之前启动事务,并在方法执行结束时关闭事务,添加如下类:

public aspect TxAspect {
    
	Object around() : call(* UserService.login(..)) {
		System.out.println("模拟开启事务");
		Object rvt = proceed();
		System.out.println("模拟结束事务");
		return rvt;
	}
}

ps:proceed() 代表回调原来的目标方法,这样位于 proceed() 之前的代码就会被添加在目标方法之前,位于 proceed() 方法之后的代码就会被添加在目标方法之后;而且这里不可以再使用 * 通配符匹配所有方法,否则方法自己也会将自己看作切入点,进而产生无限递归,最后栈溢出。

编译之后,控制台输出:

模拟进行权限检查...
模拟开启事务
模拟进行权限检查...
执行 login() 方法
模拟记录日志...
模拟结束事务
模拟记录日志...