目录
代理
1.代理是什么
给目标对象提供一个代理对象,并且由代理对象控制对目标对象的引用
代理本身是一种设计模式,用于为其他对象提供一种代理以控制对这个对象的访问。
举一个简单例子
假如现在要你写一个系统向银行转账
首先你需要先去在一个类中完成转账的方法,要想调用当前转账方法就必须做
1.验证,如用户验证判断用户的身份是否正确以及转账金额验证,验证成功
2.转账
3.事后服务
根据以往的经验来说,不做任何的强调,正常写的话,就很有可能吧这三部分的东西混写成一个大的方法。
但是这样并不好,验证、转账、事后服务都是极其复杂的流程,如果全部写在一个方法中,就会使这个方法功能量太大。
可能你就会想到,把一个方法转换为三个方法,按照顺序执行,每个方法都能完成单独的功能,不会造成冗余,这样是可行的,但是还有一个扩容的问题。
再举个例子
银行转账要求开放对支付宝,微信的转账
这就意味着,开放当前转账的接口,让支付宝和微信将其代理,把判断用户身份以及事后服务这两个部分,交给支付宝和微信自身处理,用户通过支付宝和微信的代理来实现转账这一核心方法,支付宝和微信代理着银行的转账,这个模式其实就是代理模式。
2.代理模式的好处
- 防止用户直接访问核心方法带来一些不必要的危机
- 能够对核心方法进行功能的增强!
3.java代理
代理模式分为:基于jdk实现的静态代理、基于jdk实现的动态代理、基于CGLB实现的动态代理
基于jdk实现的静态代理
图示法
核心类也是目标类,核心对象也是目标对象。
核心类,会生成核心对象,代理类去实现当前代理对象,再由代理对象去代理当前这个核心对象,这个过程是一个代理的过程,同时还有一个接口,核心类和代理类都会区实现当前接口,这就是静态代理的模式。
用代码去实现:
ZhuanZhang接口,定义出核心方法
package 代理;
public interface ZhuanZhang {
//定义核心方法
public void zhuanzhang(String A,String B,Double money);
}
YinHang核心类,实现ZhuanZhang接口,实现zhuanzhang方法
package 代理;
public class YinHang implements ZhuanZhang{
@Override
public void zhuanzhang(String A, String B, Double money) {
System.out.println(A+"给"+B+"转了"+money+"元");
}
}
ZhiFuBao代理类,实现ZhuanZhang接口,实现zhuanzhang方法,并添加验证和事后服务功能
package 代理;
/*
* 接口起到的作用就是通知代理类,所代理的核心是什么
* */
public class ZhiFuBao implements ZhuanZhang{
//定义好被代理类------》核心类
private YinHang yinHang = new YinHang();
private void yanzheng(String A,String B,Double money){
System.out.println("对A进行了身份验证");
System.out.println("对B进行了身份验证");
System.out.println("对转账金额进行了验证");
}
@Override
public void zhuanzhang(String A, String B, Double money) {//核心方法的实现
yanzheng(A,B,money);
yinHang.zhuanzhang(A,B,money);
fuwu();
}
private void fuwu(){
System.out.println("转账完成后进行服务");
}
}
Test类,用来测试
package 代理;
public class Test {
public static void main(String[] args) {
ZhiFuBao zhiFuBao = new ZhiFuBao();
zhiFuBao.zhuanzhang("张三","李四",100.0);
}
}
输出结果为:
对A进行了身份验证
对B进行了身份验证
对转账金额进行了验证
张三给李四转了100.0元
转账完成后进行服务
内存图为
用户调用代理对象,由代理对象再去调用核心对象。
接口这里起到沟通的作用
静态代理的缺陷
随着代理类所代理的目标类增多,每增加一个目标类,就需要对代理类进行扩充。
每个代理对象代理的目标太多
用一个代理类代理多个目标类是很难实现的
- 如果接口中的方法很多,那么代理类中也需要实现相同数量的方法,这会导致代理类变得庞大且难以维护。
- 如果被代理类有很多,那么就需要为每一个被代理类都编写一个代理类,这进一步增加了代码的冗余和复杂性。
基于jdk实现的动态代理
动态代理生成代理对象,分别只包含自己要代理的对象。
代码示例
Shoes接口
package 动态代理;
public interface Shoes {
public void ByShoes(String size);
}
Clothes接口
package 动态代理;
public interface Clothes {
public void ByClothes(String size);
}
ClothesFactory类实现Clothes接口,实现ByClothes方法
package 动态代理;
public class ClothesFactory implements Clothes {
@Override
public void ByClothes(String size) {
System.out.println("定制一件大小为"+size+"的衣服");
}
}
ShoeFactory类实现Shoes接口,实现BByShoes方法
package 动态代理;
public class ShoeFactory implements Shoes{
@Override
public void ByShoes(String size) {
System.out.println("定制一款大小为"+size+"的鞋子");
}
}
DTXSD 实现InvocationHandler接口,实现getProxyInstance(),invoke(),fuwu()方法
package 动态代理;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DTXSD implements InvocationHandler{
private Object object;
public DTXSD(Object o) {//传入目标类的目标对象(代理类的代理对象) 动态代理类一对一的形成
object = o;
}
/**
* 动态代理实现相关接口
* 调用该方法你就知道了目标类当中的核心方法是什么
* @return
*/
public Object getProxyInstance(){ //object.getClass() 获取目标类的类对象 getInterfaces()获取目标类的接口
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);
}
//固定写法
//三个参数的讲解
//1.Object:jdk创建的代理类,无需赋值
//2.Method:目标类当中的方法,jdk提供,无需赋值
//3.Object[]:目标类当中的方法的参数,jdk提供,无需赋值
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(object,args);
fuwu();
return null;
}
private void fuwu(){
System.out.println("销售店进行一系列的服务");
}
}
Test类
package 动态代理;
public class Test {
public static void main(String[] args) {
ClothesFactory clothesFactory = new ClothesFactory();//可以使用反射创建对象
DTXSD dtxsd1 = new DTXSD(clothesFactory);
//已经知道了目标类当中的核心方法是什么
Clothes clothes = (Clothes) dtxsd1.getProxyInstance();//用相关接口来进行接收
clothes.ByClothes("XXL");//使用相关接口来调用当前方法
ShoeFactory shoeFactory =new ShoeFactory();
DTXSD dtxsd2 = new DTXSD(shoeFactory);
Shoes shoes = (Shoes) dtxsd2.getProxyInstance();
shoes.ByShoes("42");
}
}
输出结果为:
定制一件大小为XXL的衣服
销售店进行一系列的服务
定制一款大小为42的鞋子
销售店进行一系列的服务