tinySpring Aop 分析笔记(1)
项目学习地址:code4craft/tiny-spring
step-7-method-interceptor-by-jdk-dynamic-proxy
step 7 针对有接口的情况,采用 jdk 动态代理的方式实现 AOP。
另一种情况是:无接口时,创建子类,然后进行增强(调用父类的方法),实现动态代理的实现。即 cglib 动态代理。
1 | // JdkDynamicAopProxyTest.java |
Joinpoint:被代理的对象,其实是指代码的横向插入点。
首先拿到
TargetSource
,然后拿到TimerInterceptor
,设置到AdvisedSupport
的成员属性中。- 其中的
TargetSource
是指被代理的对象,即等待增强功能的那个类(本文指 helloWorldService.java)。 - 其中的
TimerInterceptor
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12public class TimerInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
long time = System.nanoTime();
System.out.println("Invocation of Method " + invocation.getMethod().getName() + " start!");
Object proceed = invocation.proceed();
System.out.println("Invocation of Method " + invocation.getMethod().getName() + " end! takes " + (System.nanoTime() - time)
+ " nanoseconds.");
return proceed;
}
}- 在 invocation 执行前后分别往 console 输出一句话,而且计算时间差。
- 其中的
将上面拿到的
advisedSupport
设置到JdkDynamicAopProxy
中,然后通过getProxy()
的方法,获取代理。- 其中的
getProxy()
的方法会直接调用newProxyInstance()
方法(见以下代码)。 方法中分别传入:① 类加载器;② 需要实现的接口数组;③ InvocationHandler接口。newProxyInstance()
方法做了两件事情:调用
getProxyClass()
方法,创建代理类cl
(此时 cl 中仅有:$Proxy1 这一个 Class),并不是 HelloWorldService 这个类的代理。实现了 interfaces 的接口,同时继承了 Proxy 类,见以下代码:1
Class<?> cl = getProxyClass0(loader, intfs);
实例化代理类。在构造方法中将
JdkDynamicAopProxy
类(这才是 HelloWorldService 这个类的代理)传入代理类中,1
Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { advised.getTargetSource().getTargetClass() }, this);
- 其中的
说明:
这个代理的逻辑是:
- 包装实现类;
- 将
HelloWorldService
包装起来。
- 将
- 添加自定义逻辑;
- 配置拦截器
TimerInterceptor
,设置前置代码和后置代码。 - 将拦截器设置到代理类中。
- 配置拦截器
- 在使用的时候,用代理类来生成实例。
- 即由
JdkDynamicAopProxy
来执行方法(比如.helloWorld()方法)。
- 即由
- 包装实现类;
当执行
.helloWorld()
方法时,TimerInterceptor.invoke()
方法会被触发(本代码中无论什么切点,都会执行此方法),然后将相关参数传入ReflectiveMethodInvocation()
中,1
2
3
4
5
6@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
MethodInterceptor methodInterceptor = advised.getMethodInterceptor();
return methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method,
args));
}