概念
当无法或不想直接访问本对象时,可以为其他对象提供一种代理来控制对本对象的访问。
实现方式
- Subject —— 抽象主题类。是委托类和代理类的共同接口或抽象类
- RealSubject ——委托类。客户端通过代理类间接调用委托类的方法
- Proxy —— 代理类,持有委托类的引用,在接口方法中调用委托类相应的接口方法执行。
1 静态代理
public interface Subject {
void submit();
}
public class RealSubject implements Subject {
@Override
public void submit(){
System.out.println("提交了");
}
}
public class MProxy implements Subject {
private Subject msubject;
public Proxy (Subject s){
subject = s;
}
@Override
public void submit()[
s.submit();
}
}
public class Test{
public static void main(String[] args){
Subject s = new RealSubject();
Subject p = new MProxy(s);
p.submit();
}
}
2 动态代理
public class DyTest {
/**
* 抽象主题
*/
public interface Subject {
void buy();
}
/**
* 具体主题1,米粉
*/
public class XiaoMiFun implements Subject {
@Override
public void buy() {
System.out.println("买小米");
}
}
/**
* 苹果粉
*/
public class IphoneFun implements Subject {
@Override
public void buy() {
System.out.println("买苹果");
}
}
/**
* 调用处理器
* 1 生成动态代理对象
* 2 指定动态代理对象运行目标对象需要完成的任务
*/
public class DynamicProxy implements InvocationHandler {
// 声明代被理对象
// 作用:绑定关系,即关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke()
private Object proxyObject;
public Object newProxyInstance(Object proxyObject) {
this.proxyObject = proxyObject;
return Proxy.newProxyInstance(proxyObject.getClass().getClassLoader(),
proxyObject.getClass().getInterfaces(), this);
// Proxy.newProxyInstance()作用:根据指定的类装载器、一组接口 & 调用处理器 生成动态代理类实例,并最终返回
// 参数1:指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
// 参数2:指定目标对象的实现接口
// 即要给目标对象提供一组什么接口。若提供了一组接口给它,那么该代理对象就默认实现了该接口,这样就能调用这组接口中的方法
// 参数3:指定InvocationHandler对象。即动态代理对象在调用方法时,会关联到哪个InvocationHandler对象
}
// 复写InvocationHandler接口的invoke()
// 动态代理对象调用目标对象的任何方法前,都会调用调用处理器类的invoke()
// 参数1:动态代理对象(即哪个动态代理对象调用了method()
// 参数2:目标对象被调用的方法
// 参数3:指定被调用方法的参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代购出门了, proxy name = " + proxy.getClass().getName());
Object result = null;
// 通过Java反射机制调用目标对象方法
result = method.invoke(proxyObject, args);
return result;
}
}
public void test() {
// 创建调度器对象
DynamicProxy dynamicProxy = new DynamicProxy();
// 创建目标对象
XiaoMiFun miFun = new XiaoMiFun();
// 创建代理类对象
Subject phoneProxy = (Subject) dynamicProxy.newProxyInstance(miFun);
// 代购
phoneProxy.buy();
// 代购苹果
IphoneFun iphoneFun = new IphoneFun();
dynamicProxy.newProxyInstance(iphoneFun);
phoneProxy.buy();
}
public static void main(String[] args) {
DyTest dyTest = new DyTest();
dyTest.test();
}
}
动态代理相对于静态代理来说对代理者和委托类进行解耦,使两者没有直接耦合,可以用一个代理类代理N个委托类