前言
最近在学习研究Mybatis的底层 实现原理 ,发现Mybatis使用了很多的设计模式。
其中 代理模式可以认为是Mybatis的核心使用的模式,正是由于这个模式,我们只需要编写Mapper.java接 口,不需要实现,由Mybati s后台帮我们完成具体SQL的执行。
本文将整理总结一下 JDK的动态代理和静态代理;
参考博客
- https://blog.csdn.net/familyshizhouna/article/details/78905997
- https://www.cnblogs.com/haodawang/p/5967185.html
什么是反射
(ps: 要了解代理,首先就要对java的反射机制有一度 的了解)
- 说明
java的反射机制,是说在运行时刻,对于任何一个类,都能够知道它的所有属性和方法; 对任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用方法的功能称为java的反射机制。 - 总结
在程序运行的时候 动态的加载类和类的信息。
(ps:更多基础的使用方法 见我的博客 https://blog.csdn.net/qq_38749759/article/details/105627721)
静态代理
- 原理图
- 说明
代理类和实现类实现同一个接口,代理类有一个实现类的引用,
客户调用代理类的方法时,代理类就调用实现类的方法。
称为静态,是因为代理类和实现类是写死的,就是在编译阶段就确定的
(ps: 个人感觉和本地的调用差不多)
动态代理
如果有好多类要代理,就要写好几个代理类,这样比较麻烦,这时动态代理就有用了,
动态代理的本质就是用户提供类名、方法名、参数,代理类执行方法,返回结果。
用类加载器可以将类加载到虚拟机,用Class clazz表示,有这个对象,就可以执行它的方法。(这就是反射)
这就实现了动态代理。
- 原理图
* 代码示例
package com.edu.emple4;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author bggl
* @date 2019/6/12- 18:26
*/
interface Hose{
void maifang();
}
class Bggl implements Hose {
@Override
public void maifang() {
System.out.println("我是bggl,开始买房");
}
}
//jdk动态代理
class JdkProxy implements InvocationHandler{
private Object target;
JdkProxy(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是中介,买房交给我");
Object invoke = method.invoke(target, args);
System.out.println("我是中介,买房结束");
return invoke;
}
}
public class Test {
public static void main(String[] args) {
Bggl bggl = new Bggl();
JdkProxy jdkProxy = new JdkProxy(bggl);
Hose o = (Hose) Proxy.newProxyInstance(bggl.getClass().getClassLoader(), bggl.getClass().getInterfaces(), jdkProxy);
o.maifang();
}
}
注: new JdkProxy(bggl) ==》也可以使用匿名内部类的方式 对invoke方法进行增强
补充
关于代理 ,经常可以听到正向代理和反向代理,他们的区别如下
正向代理隐藏真实客户端, 反向代理隐藏真实服务端