代理模式定义(Proxy):提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样就可以在不修改原目标对象的前提下,提供额外的操作功能,扩展目标对象的功能
一、静态代理
常用于对原有业务逻辑的扩充,通过让代理类持有真实对象,然后再原有代码中调用代理类方法。
公共接口:
public interface Action { void doSomething();
}
public class RealObject implements Action{
@Override
public void doSomething() {
System.out.println("真实设备操作.......");
}
}
public class ProxyObject implements Action{ private Action realObject; public ProxyObject(Action realObject){
this.realObject = realObject;
} @Override
public void doSomething() {
System.out.println("开启代理");
realObject.doSomething();
}
}
public class Client { public static void main(String []args){ ProxyObject proxyObject = new ProxyObject(new RealObject());
proxyObject.doSomething();
}
}
静态代理比较简单,通过 proxy 持有真实对象的引用,并进行一层封装。
静态代理的优缺点:
优点:扩展原功能,不侵入原代码
缺点:原对象多个方法需要代理时,导致 proxy 膨胀
二、动态代理
动态代理指在运行时动态生成代理类。即代理类的字节码将在运行时生成并载入当前代理的 ClassLoader 。 与静态代理处理类相比,动态代理有相当好处。
动态代理类使用字节码动态生成加载技术,在运行时生成加载类。生成动态代理类的方法很多,如 jdk 自带的动态代理,cglib ,javassist 或者 ASM 库。cglib 和 javassist
是高级的字节码生成库,性能比JDK 自带的动态代理好。ASM 是低级的字节码生成工具。
方法一:使用 cglib
动态的生成一个子类,然后子类覆盖代理类中的方法,如果是 private 或者 final 修饰的方法,中则不会被重写
cglib 是一个开源项目,代码托管在 github ,地址:https://github.com/cglib/cglib
方法二、Jdk 自带的动态代理
接口:
public interface Subject {
public int sellBooks(); public String speak();
}
真实对象:
public class RealSubject implements Subject{
@Override
public int sellBooks() {
System.out.println("卖书");
return 1 ;
} @Override
public String speak() {
return null;
}
}
处理器对象:
public class MyInvocationHandler implements InvocationHandler{
/**
* 因为需要处理真实角色,所以要把真实角色传进来
*/
Subject realSubject ; public MyInvocationHandler(Subject realSubject) {
this.realSubject = realSubject;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启代理。。。。。");
if(method.getName().equals("sellBooks")){
int invoke = (int)method.invoke(realSubject,args);
System.out.println("调用的是卖书的方法");
return invoke ;
}else {
String string = (String)method.invoke(realSubject,args);
System.out.println("调用的是说话的方法");
return string ;
}
}
}
测试端:
public class Client { public static void main(String []args){ Subject realSubject = new RealSubject(); MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realSubject); Subject proxyClass = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Subject.class},myInvocationHandler); proxyClass.sellBooks(); proxyClass.speak();
}
}