代理模式总结
一 . 什么是代理模式?
举一个生活中的案列, 一个人想要解决法律纠纷, 但是他并不懂法律,所以他就可以选择去请律师,律师就负责去完成这个人不能完成的事情,这个人只负责提供一些基本的证据及线索等等。这就是一个典型的代理, 这就完成了业务的增强,这也是代理存在的意义。
- 应用场景:用于对原生函数——法律诉讼,的增加与扩展。
- 工作模块:分为被代 理对象——要提出法律诉讼的这个人,与代理对象——律师。
二 . java中的代理分类
整体可以分为静态代理和动态代理
1. 静态代理
静态代理主要是在编写代码时由我们手动编写代理类去实现拓展的功能,之所以称之为静态,是因为所有的代理关系全部都是固定死的。就像上面的场景中,他们的关系是1对1固定的。
2.动态代理
动态代理相对于静态代理,最大的变化就是不用手动去实现自己的代理类了,只需要通过JDK或者CGLIB去获得一个代理类,而代理类是在运行时被生成与加载的。动态代理就是将我们手动编写代理实现这一过程变成了由框架自己去完成,然后再自己加载运行。框架是如何完成的呢?我们知道代码都会成为.java文件,然后编译成.class文件,最终加载进JVM成为一个类。框架就是在运行时,帮我们生成代理类对应的java/class文件,然后再加载进JVM成为一个类,最终反射创建对应的代理对象返回给我们去使用。
三.实现
代理实现的前提是如何能够获取到原接口的调用。因此就可以有两种方式:组合与继承。
- 组合:与被代理类实现相同的接口,然后向代理类传入被代理类的引用,从而调用到目标函数。
- 继承:继承被代理类,重写目标函数,然后通过super调用到目标函数。
1.静态代理–组合(实现相同接口)
1) 定义了一个所有老师的一个接口
public interface AllTeacher {
public void teach();
}
2) 一个具体的老师实现了这个接口,重写了teach方法
public class MusicTeacher implements AllTeacher{
@Override
public void teach() {
System.out.println("教音乐");
}
}
- 代理对象也实现了这个接口,并包含这个MusicTeacher类对象,对musicTeacher的功能做了进一步增强。
public class TeacherProxy implements AllTeacher {
MusicTeacher musicTeacher;
public TeacherProxy(MusicTeacher musicTeacher){
this.musicTeacher = musicTeacher;
}
@Override
public void teach() {
System.out.println("代理开始。。。");
System.out.println("教语文");
musicTeacher.teach();
System.out.println("代理结束");
}
}
2.静态代理–继承
增加了MusicTeacher的子类,调用super.teach()。
public class TeacherProxy extends MusicTeacher{
@Override
public void teach() {
System.out.println("代理开始。。。");
System.out.println("教语文");
super.teach();
System.out.println("代理结束");
}
}
3.动态代理 — JDK代理模式
public class JDKProxy {
public static void main(String[] args) {
MusicTeacher musicTeacher = new MusicTeacher();//被代理对象
AllTeacher proxyteacher = (AllTeacher) proxy(musicTeacher);
proxyteacher.teach();
}
public static <T> T proxy(T t){
T ret = (T) Proxy.newProxyInstance(t.getClass().getClassLoader(),//类加载器
t.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//重写方法
System.out.println("开始代理。。。");
System.out.println("教语文");
Object ret = method.invoke(t,args);
System.out.println("代理结束");
return ret;
}
});
return ret;
}
}
4 . 动态代理 --CGLIB代理模式
核心就是拦截父类的所有函数,然后通过调用子类的方法去实现增强。
public class CGLIBProxy {
public static void main(String[] args) {
MusicTeacher musicTeacher = new MusicTeacher();//被代理对象
MusicTeacher proxyteacher = (MusicTeacher) proxy(musicTeacher);
proxyteacher.teach();
}
public static <T> T proxy(T t){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(t.getClass());// 创建传入的类的子类
// 完成创建后 回调自己
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//重写方法
System.out.println("开始代理。。。");
System.out.println("教语文");
Object ret = methodProxy.invoke(t,objects);
System.out.println("代理结束");
return ret;
}
});
return (T) enhancer.create();
}
}