代理模式介绍
代理模式,顾名思义,代理就是不自己做,让别人来帮忙做,现实中有很多例子,比如中介公司,婚介所,这些都是代理典型的代理机构,比如我想找一个女朋友,但是由于我的脸皮比较薄,不好意思和女孩子说话,更没有搭讪的勇气,于是乎,我找到了我的好朋友mikey老师,让他给我介绍一下,他答应了我的请求,于是我就去专心写代码了,女朋友的事情就交在他身上了,我不去瞎操心了。
Java语言来表示这一过程
定义一个接口
代码语言:javascript复制public interface IPeople {
//找女朋友
void findGirlFriend();
}
单身狗steakliu委托mikey老师帮忙找女朋友
代码语言:javascript复制public class Steak implements IPeople{
private final MikeyTeacher mikeyTeacher;
public Steak(MikeyTeacher mikeyTeacher){
this.mikeyTeacher = mikeyTeacher;
}
@Override
public void findGirlFriend() {
System.out.println("steak: 我想找一个女朋友,委托了mikey老师帮我找");
//委托mikey老师去找
mikeyTeacher.findGirlFriend();
System.out.println("steak: mikey老师给我找到了女朋友,我现在开始交往了");
}
}
mikey老师
代码语言:javascript复制public class MikeyTeacher implements IPeople{
@Override
public void findGirlFriend() {
System.out.println("mikey: 接受了steak的请求,我现在疯狂的帮他找女朋友");
}
}
测试
代码语言:javascript复制public class Test {
public static void main(String[] args) {
Steak steak = new Steak(new MikeyTeacher());
steak.findGirlFriend();
}
}
输出:
steakliu: 我想找一个女朋友,委托了mikey老师帮我找
mikey: 接受了steakliu的请求,我现在疯狂的帮他找女朋友
steakliu: mikey老师给我找到了女朋友,我现在开始交往了
自从mikey老师给我介绍成功了女朋友过后,在圈内传开了名,大群的单身狗都找到了mikey老师,当然mikey老师也是很乐意的,不过现在mikey老师只能服务steakliu一个人(静态代理),于是mikey老师从新改造了下自己,不再只为steakliu服务,而是为更多的单身狗服务(Jdk动态代理),现在mikey老师啥也不说,就开始改造了。
接口依然没有变
代码语言:javascript复制public interface IPeople {
//找女朋友
void findGirlFriend();
}
mikey老师,实现了InvocationHandler 接口
代码语言:javascript复制public class MikeyProxyTeacher implements InvocationHandler {
private IPeople people;
//获取对象实例
public IPeople getPeopleInstance(IPeople people){
this.people = people;
return (IPeople) Proxy.newProxyInstance(people.getClass().getClassLoader(),people.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("mikey老师:我现在开始帮广大单身网友找女朋友");
Object response = method.invoke(people,args);
System.out.println("mikey老师:为单身网友找到女朋友");
return response;
}
}
单身狗steakliu
代码语言:javascript复制public class Steak implements IPeople {
@Override
public void findGirlFriend() {
System.out.println("单身网友steak: 我想找一个女朋友,委托了mikey老师帮我找");
}
}
测试
代码语言:javascript复制public class Test {
public static void main(String[] args) {
MikeyProxyTeacher mikeyProxyTeacher = new MikeyProxyTeacher();
IPeople instance = mikeyProxyTeacher.getPeopleInstance(new Steak());
instance.findGirlFriend();
}
}
结果
mikey老师:我现在开始帮广大单身网友找女朋友
单身网友steakliu: 我想找一个女朋友,委托了mikey老师帮我找
mikey老师:为单身网友找到女朋友
现在单身网友tlgen也想找一个女朋友,找到了mikey老师,于是只需要拿到mikey老师的“介绍说明书”,就可以了
代码语言:javascript复制public class Tlgen implements IPeople {
@Override
public void findGirlFriend() {
System.out.println("单身网友tlgen: 我想找一个女朋友,委托了mikey老师帮我找");
}
}
测试
代码语言:javascript复制public class Test {
public static void main(String[] args) {
MikeyProxyTeacher mikeyProxyTeacher = new MikeyProxyTeacher();
IPeople instance = mikeyProxyTeacher.getPeopleInstance(new Tlgen());
instance.findGirlFriend();
}
}
结果
mikey老师:我现在开始帮广大单身网友找女朋友
单身网友tlgen: 我想找一个女朋友,委托了mikey老师帮我找
mikey老师:为单身网友找到女朋友
mikey老师的介绍的人越来越多,这时候,只是每个网友都需要拿到mikey老师的“介绍说明书”(实现接口),mikey老师才能帮其介绍女朋友,很多网友不愿意了,于是mikey老师又想出了一个策略,网友不用拿到“介绍说明书”也行(cglib动态代理),mikey老师开始改造。
mikey老师实现了MethodInterceptor 接口
代码语言:javascript复制public class MikeyCglibProxyTeacher implements MethodInterceptor {
private final Enhancer enhancer = new Enhancer();
public Object getProxy(Class<?> clazz){
if (clazz == null){
throw new RuntimeException("get object instance the param does not null");
}
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("mikey老师:我现在开始帮广大单身网友找女朋友");
Object response = methodProxy.invokeSuper(o, objects);
System.out.println("mikey老师:为单身网友找到女朋友");
return response;
}
}
这时单身网友JiaCong和哥几个来找女朋友了。
代码语言:javascript复制public class JiaCong {
public void findGirlFriend() {
System.out.println("单身网友JiaCong: 我想找一个女朋友,委托了mikey老师帮我找");
}
}
mikey老师帮JiaCong开始找女朋友
代码语言:javascript复制public class Test {
public static void main(String[] args) {
MikeyCglibProxyTeacher mikeyCglibProxyTeacher = new MikeyCglibProxyTeacher();
JiaCong proxy = (JiaCong) mikeyCglibProxyTeacher.getProxy(JiaCong.class);
proxy.findGirlFriend();
}
}
结果
mikey老师:我现在开始帮广大单身网友找女朋友
单身网友JiaCong: 我想找一个女朋友,委托了mikey老师帮我找
mikey老师:为单身网友找到女朋友
总结
mikey老师和单身狗网友的故事就讲完了,从中我们引出了静态代理,Jdk动态代理和cglib动态代理,Jdk动态代理是代理接口,cglib动态代理是代理类,二者都有不同的使用场景,需要根据自己的需求去选择。
使用场景
代理模式使用也十分频繁,比如spring的aop就是典型的代理模式,aop切面就是将与主业务不相关的功能抽离出来,通过切面的方式去使用,比如日志记录,接口权限等。
最后单身狗朋友们赶快去找mikey老师吧