ByxAOP是一个基于JDK动态代理的简易AOP框架,具有以下功能特性:
- 对目标对象的特定方法进行拦截和增强
- 支持灵活的拦截规则和自定义拦截规则
- 动态实现接口和批量实现接口方法
- 灵活的对象代理机制
项目地址:github 码云
使用示例
首先来通过一个简单例子快速了解ByxAOP。
假设我们有一个UserDao
接口:
public interface UserDao{ int listAll(); int listById(int id); void deleteByName(String name);}
UserDao
接口有一个UserDaoImpl
实现类:
public class UserDaoImpl implements UserDao{ @Override public int listAll() { System.out.println("正在执行listAll方法"); return 123; } @Override public int listById(int id) { System.out.println("正在执行listById方法:id = " + id); return 456; } @Override public void deleteByName(String name) { System.out.println("正在执行deleteByName方法:name = " + name); }}
现在我们来完成一个需求:拦截UserDaoImpl
中所有以list
开头的方法,即listAll
和listById
方法,拦截过程中打印出目标方法的一些相关信息。使用ByxAOP来完成这个需求,只需要三个步骤:
第一步:创建一个方法拦截器(
MethodInterceptor
):MethodInterceptor interceptor = (signature, targetMethod, params) ->{ System.out.println("开始拦截" + signature.getName() + "方法"); System.out.println("原始参数:" + Arrays.toString(params)); Object ret = targetMethod.invoke(params); System.out.println("原始返回值:" + ret); System.out.println("结束拦截" + signature.getName() + "方法"); return ret;};
MethodInterceptor
是ByxAOP中用来表示方法拦截器的核心接口,signature
是目标方法签名,targetMethod
用于调用目标方法,params
是传递给目标方法的参数。在interceptor
中,首先打印了拦截开始信息、目标方法的方法名和原始参数,然后调用了目标方法并获取返回值,最后打印了返回值和拦截结束信息。关于
MethodInterceptor
接口及其相关方法和参数的详细介绍,请看下文。第二步:创建一个方法匹配器(
MethodMatcher
):MethodMatcher matcher = withPattern("list(.*)").andReturnType(int.class);
MethodMatcher
的构建使用了一种被称为“流畅接口”的API设计风格,通过链式调用以及特定的命名来达到很好的可读性。withPattern
匹配方法名满足指定正则表达式的方法,andReturnType
则在上一个匹配器的基础上增加了返回值类型的条件。整个matcher
表示匹配所有方法名以list
开头且返回值为int
类型的方法。MethodMatcher
接口有很多预定义的实现类,通过组合这些类可以非常灵活地配置拦截规则,请看下文的详细介绍。第三步:创建AOP代理对象:
UserDao userDao = proxy(new UserDaoImpl(), interceptor.when(matcher));
proxy
方法是AOP
类中的一个静态方法,用于创建AOP代理对象。第一个参数传入目标对象(被增强的对象),第二个参数传入方法拦截器。对于目标对象中的每一个方法调用,都会被该方法拦截器拦截。不过请注意,这里我们用interceptor.when(matcher)
指定了拦截条件。由于match
匹配以list
开头且返回值为int
类型的方法,所以只有满足这个条件的方法才会被intercept
拦截。
到这里,代理对象userDao
就被创建出来了,现在让我们来调用一下userDao
中的各个方法:
userDao.listAll();System.out.println();userDao.listById(1001);System.out.println();userDao.deleteByName("XiaoMing");
控制台输出如下:
开始拦截listAll方法原始参数:null正在执行listAll方法原始返回值:123结束拦截listAll方法开始拦截listById方法原始参数:[1001]正在执行listById方法:id = 1001原始返回值:456结束拦截listById方法正在执行deleteByName方法:name = XiaoMing
从输出结果可以看到,UserDaoImpl
中的listAll
方法和listById
方法都被增强了,相应的信息也打印出来了,而deleteByName
方法没有被增强。
下面将介绍ByxAOP的设计。
MethodInterceptor接口
首先来介绍一下MethodInterceptor
接口,它是ByxAOP中的核心接口之一。
MethodInterceptor
即方法拦截器,是对方法拦截过程的封装,它的定义如下:
public interface MethodInterceptor{ Object intercept(MethodSignature signature, Invokable targetMethod, Object[] params);}
当目标方法被拦截时,intercept
方法将会被调用,同时传入一些目标方法的相关信息。intercept
方法的返回值将作为代理方法的返回值。
signature
是目标方法签名,用于在拦截时获取目标方法的签名信息。signature
是MethodSignature
接口的实现类,MethodSignature
接口包含下列方法:方法
说明
getName
获取方法名
getReturnType
获取返回值类型
getParameterTypes
获取参数类型
getAnnotation
获取方法的指定注解
getAnnotation
获取方法上的指定注解
getAnnotations
获取方法上的所有注解
hasAnnotation
方法是否被某个注解标注
getParameterAnnotations
获取方法参数上的注解
isPublic
是否为public方法
isPrivate
是否为private方法
isProtected
是否为protected方法
targetMethod
是目标方法调用器,用于在拦截时调用目标方法,向目标方法传递参数,以及获取目标方法的返回值
.........