代理模式(四)之模仿spring Aop及真实jdk的动态代理

前言

代理模式,尤其是动态代理,他从思想上改变了我们对编程的认识,可以想象一个切面我们在其中添加任何控制如事务、日志、权限等,而这也是面向切面编程的核心,更是spring Aop的核心,而设计才是实用的,框架和配置都是虚的,尤其当抛开jdk底层代码设计,才发现其中的来龙去脉和乐趣。

总之,动态代理设计模式的思想太强大了。接下来将用之前模拟的jdk动态代码和jdk本身自带的动态来模拟一个案例

大概物理情景是,添加一个打野信息接口和打野代理,利用InvocationHandler实现代理对具体打野的代理

首先是一个打野接口

1
2
3
4
5
6
package com.zwl.pr;
public interface JungleInfo {
public void addJungle();
}

打野接口实现类

1
2
3
4
5
6
7
8
9
10
11
12
package com.zwl.pr;
public class JungleInfoimpl implements JungleInfo {
@Override
public void addJungle() {
System.out.println("Js is ganking");
System.out.println("Leesin is ganking");
}
}

打野代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.zwl.pr;
import java.lang.reflect.Method;
public class JungleHandler implements InvocationHandler {
private Object target;
public JungleHandler(Object target) {
super();
this.target = target;
}
@Override
public void invoke(Object o, Method m) {
//控制之前的业务逻辑
System.out.println("JungleHandler is starting");
try {
m.invoke(target);
} catch (Exception e) {
e.printStackTrace();
}
//控制之后的业务逻辑
System.out.println("JungleHandler is ending");
}
}

为了方便这里只是打印了一个语句
测试类

1
2
3
4
5
6
//被代理对象
JungleInfo jun=new JungleInfoimpl();
//代理类
InvocationHandler invo=new JungleHandler(jun);
JungleInfo jung=(JungleInfo) Proxy.newProxyInstance(JungleInfo.class, invo);
jung.addJungle();

输出结果:

class com.zwl.pr.LeeSinTimeProxy
JungleHandler is starting
Js is ganking
Leesin is ganking
JungleHandler is ending

至此我们发现如果我们想在这个切面中再加一个控制,好办,再写一个handle类,代理其它handle类,达到切面控制效果。
当然,以后只要实现InvocationHandler接口就能达到效果,而proxy底层都不需要知道

jdk的动态代理

同样是上面的例子,知识代理handler需要改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.zwl.pr;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JungleHandlers implements InvocationHandler {
private Object target;
public JungleHandlers(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Jdk is starting");
method.invoke(target, args);
System.out.println("Jdk is ending");
return null;
}
}

其中Object proxy是指代理类,Method method是指被代理的方法,Object[] args为该方法的参数数组

接下来是测试类

1
2
3
4
JungleInfo jun=new JungleInfoimpl();
JungleHandlers invo=new JungleHandlers(jun);
JungleInfo jung=(JungleInfo) Proxy.newProxyInstance(JungleInfo.class.getClassLoader(),new Class<?>[]{JungleInfo.class}, invo);
jung.addJungle();

其中jung将返回一个代理类的实例JungleInfo.class.getClassLoader()是类装载器,第二个参数是任何真实类拥有的全部接口的数组,第三个参数就是真实的handles

测试结果:

Jdk is starting
Js is ganking
Leesin is ganking
Jdk is ending

至此,我们利用动态代理,就可以在不修改原来代码的基础上,就可以在原来代码的基础上做操作,而这恰恰就是AOP编程的核心

热评文章