设计模式——动态代理
在看代码之前,我先来说说什么是静态代理和动态代理,举一个通俗易懂的例子:
- 你想约你的女神约会,你的女神不在家,你得让她的家人叫她。这里你就是一个对象,你的女神就是一个被代理的类,她的家人就是一个代理人。她的家人在把她交给你之前得先调查你的背景,在她被你约出去之后还要关心你有没有对她女儿动手动脚,她呢,就只管跟你约会、看电影其他的事情不用考虑,不过再你每次约会看电影之前,她的家人都要对你进行前后的检查,如果你使用静态代理,每次就只能对对象进行两个操作,就是调查背景,有没有动手动脚,事先必须规定好内容。但是如果你使用动态代理,你可以进行多个操作,事先不能规定好内容,在创建对象的时候实现你需要的功能就好了,例子举到这里我们来看看代码。
首先是静态代理,我就直接写在一个类中了
public class StaticProxy { public static void main(String[] args) { //代理类(住户) ProxyObject proxy = new ProxyObject(new RealObject()); proxy.action(); } } //共公的接口 interface Interface{ void action(); } //被代理类(业主) class RealObject implements Interface{ @Override public void action() { System.out.println("aaaaaaaaaa"); } } //代理类(中介) class ProxyObject implements Interface{ RealObject real; //被代理对象的声明 public ProxyObject(RealObject real) { this.real = real; } @Override public void action() { System.out.println("和业主收取费用"); real.action(); //被代理类的行为 System.out.println("和住户收取费用"); } }- 这种模式在程序运行之前就已经生成了.class文件,只能代理一个类,事先还要知道代理的内容
下面是重点,我用学生登陆来讲解动态代理
首先是一个Student接口,就是所要实现的功能
//定义一个公共的接口 public interface Student { public void login();//登录功能 public void submit();//提交功能 }然后定义一个StudentImp来实现Student接口,类似于房东
public class StudentImp implements Student { //重写接口中的方法,加入你要实现的功能 @Override public void login() { System.out.println("登录"); } @Override public void submit() { System.out.println("提交"); } }然后定义一个类,来实现jdk里的InvocationHandler的接口,类似于中介
package com.yzy.agent; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * @className MyInvacationHandler.java * @author yangsir * @version V1.0 * @date 2019年8月17日-上午9:29:41 * @description *定义一个类,来实现jdk里的InvocationHandler的接口,类似于中介 */ public class MyInvacationHandler implements InvocationHandler { Object obj;//这里定义一个obj类,是为了传参,意思就是中介带()来看房子,()里面就是obj public MyInvacationHandler(Object obj) {//对应的有参构造 this.obj = obj; } @Override //实现InvocationHandler接口要重写里面的抽象方法,invoke就是里面的唯一方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//参数列表也相同,抛出异常 //在每次实现操作之前进行校验跟记录,就好比你登录QQ的时候首先要进行校验,然后QQ会把你的登录信息记录在日志里,输好了账号密码准备提交的时候相同的操作还要再来一遍 System.out.println("权限校验"); //Method是反射里面用来获取对象方法的一个方法,有点绕,意思就是这个方法的作用就是用来获取其他方法的,它需要两个参数,(对象,对象数组)我们按照要求的传给它即可 method.invoke(obj, args); System.out.println("日志记录"); //直接返回空即可,我们的目的是输出上面两个语句 return null; } }最后是测试类
package com.yzy.agent; import java.lang.reflect.Proxy; /** * @className TestDynamicProxy.java * @author yangsir * @version V1.0 * @date 2019年8月17日-上午9:22:05 * @description *测试类 */ public class TestDynamicProxy { public static void main(String[] args) { // 创建一个实现了Student接口的StudentImp类,类似于找房东拿钥匙 StudentImp stu = new StudentImp(); // 创建一个实现了InvacationHandler接口的MyInvacationHandler类,类似于找中介看房 MyInvacationHandler m = new MyInvacationHandler(stu); /* 用一个接口对象作为返回值,这里要进行强转,默认是Object类型的,我们要调用反射中Proxy里面的一个静态方法,直接类名.调用, 然后它需要三个参数,(类加载器,类所要实现的接口,对象),stu.getClass是反射中获取类的字节码文件然后再.getClassLoader 是获得类的加载器,后面的.getInterfaces就是获得所有实现的接口,m为对象 */ Student s = (Student) Proxy.newProxyInstance(stu.getClass().getClassLoader(), stu.getClass().getInterfaces(),m); // 最后登录并提交 s.login(); s.submit(); } }- 动态代理是程序在运行的时候通过反射机制生成的,通常会代理接口下的所有类,实现不用知道所要实现的功能,在运行的时候才会确定。必须实现InvocationHandler接口,使用Proxy类中的newProxyInstance方法
设计模式之代理模式、动态代理模式、Cglib代理模式动态代理是代理模式吗
【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )动态代理是代理模式吗
设计模式之代理模式(包含静态代理和动态代理)设计模式的代理模式
Java设计模式--代理模式--静态代理/动态代理--使用/详解/实例java设计模式之代理模式
代理模式-静态代理模式 代理模式-动态代理(基于接口,JDK动态代理)动态代理是代理模式吗
#yyds干货盘点# 设计模式之静态代理,jdk动态代理,cglib动态代理的区别jdk静态代理和动态代理
【设计模式】代理模式 ( 动态代理 | 模拟 Java 虚拟机生成对应的 代理对象 类 )设计模式的代理模式