设计模式——动态代理

在看代码之前,我先来说说什么是静态代理和动态代理,举一个通俗易懂的例子:

  • 你想约你的女神约会,你的女神不在家,你得让她的家人叫她。这里你就是一个对象,你的女神就是一个被代理的类,她的家人就是一个代理人。她的家人在把她交给你之前得先调查你的背景,在她被你约出去之后还要关心你有没有对她女儿动手动脚,她呢,就只管跟你约会、看电影其他的事情不用考虑,不过再你每次约会看电影之前,她的家人都要对你进行前后的检查,如果你使用静态代理,每次就只能对对象进行两个操作,就是调查背景,有没有动手动脚,事先必须规定好内容。但是如果你使用动态代理,你可以进行多个操作,事先不能规定好内容,在创建对象的时候实现你需要的功能就好了,例子举到这里我们来看看代码。

首先是静态代理,我就直接写在一个类中了

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方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DanielMaster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值