在生活中,总有一些事是我们无法亲历亲为去完成的,就比如说买火车票,我们首先想到的是网络购票,然后我们通过电子票或是去车站兑换纸质票进站。
在这个过程中,网络平台就作为我们的代理去替我们得到票,不管这个票最后是什么形式的,我们总是能进去。我们不用考虑这张票是怎么来的,具体的流程是什么,核心就是我们最后要拿到票。
静态代理模式,简单的说就是把核心代码封装给代理类,就拿买票来说,我来买票,平台就要单独为我封装一份买票代码,其他人来买票同样是如此,尽管我们都很清楚,这其中的代码都大差不差,只是换个身份证罢了,因此,静态代理的弊端就显现出来了。
动态代理,就是动态的生成代理类的过程,简单的说就是我们不需要再重复执行封装代码的过程,一个平台,一套代码,你登陆出来的就是你的票,我登陆出来的就是我的(前提是都支付了,哈哈哈哈)。
那么怎么实现jdk的动态代理呢?
首先,我们创建一个Calculator接口,里面的方法为加减乘除
public interface Calculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
接下来,创建Calculator接口的实现类CalculatorImpl
public class CalculatorImpl implements Calculator{
@Override
public int add(int i, int j) {
int result = i + j;
System.out.println("方法内部 result = " + result);
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
System.out.println("方法内部 result = " + result);
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
System.out.println("方法内部 result = " + result);
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
System.out.println("方法内部 result = " + result);
return result;
}
}
这是我们的被代理类,对应买票过程就是我们买到票
下面通过动态代理得到代理类对象
//动态代理工厂,就是为了得到代理类对象
public class ProxyFactory {
//传入被代理类对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//得到代理类对象
public Object getProxy(){
/**
* 1、classLoader:加载动态生成的代理类的类加载器
* 2、interfaces:被代理类对象实现的所有接口的class对象所组成的数组,如果有多个,那么在选择时就可以根据需要选择最终的代理类
* 3、invocationHandler:设置代理对象实现目标对象方法的过程,即代理类中如何重写接口中的核心方法
*/
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
//InvocationHandler 接口中只有一个方法InvocationHandler,需要我们去实现
InvocationHandler h = new InvocationHandler() {
/**
* proxy:代理对象,不需要我们创建,jdk自动提供
* method:代理对象需要实现的方法,即被代理类中要被调用的方法
* args:method所对应方法的参数
*/
//这里就利用到了反射
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("日志,方法"+method.getName()+"参数:"+ Arrays.toString(args));
Object result = method.invoke(target, args);
System.out.println("日志,方法"+method.getName()+"结果:"+ result);
return result;
}
};
return Proxy.newProxyInstance(classLoader,interfaces,h);
}
}
Proxy中的newProxyInstance方法: newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
上面的动态代理的功能就是动态的实现为被代理类中方法添加日志
测试动态代理结果
public class ProxyTest {
@Test
public void testProxy(){
//传入被代理类的对象
ProxyFactory proxyFactory = new ProxyFactory(new CalculatorImpl());
//我们需要通过被代理类实现的接口,确定代理类应该选择什么类型
//如果被代理类实现多个接口,那么这里就选择需要代理的功能,进而选择代理类的类型
//返回代理类对象
Calculator proxy = (Calculator) proxyFactory.getProxy();
//调用方法
proxy.div(8, 4);
}
}
成功实现动态代理。
一起学习,共同进步!
云想霓裳花想容,春风拂槛露华浓。
若非群玉山头见,会向瑶台月下逢。