共计 2937 个字符,预计需要花费 8 分钟才能阅读完成。
1. 本人实现代理类
public interface BizDemo {void helloGirl(String name);
void helloBoy(String name);
}
public class BizDemoImpl implements BizDemo{
@Override
public void helloGirl(String name) {System.out.println( name + "helloGirl in BizDemoImpl");
}
@Override
public void helloBoy(String name) {System.out.println( name + "helloBoy in BizDemoImpl");
}
}
public class BizDemoImplProxy implements BizDemo {
private BizDemo real;
BizDemoImplProxy(BizDemo real) {this.real = real;}
@Override
public void helloGirl(String name) {System.out.println("proxy by BizDemoImplProxy");
this.real.helloGirl(name);
}
@Override
public void helloBoy(String name) {System.out.println("proxy by BizDemoImplProxy");
this.real.helloBoy(name);
}
}
public static void main(String[] args) {BizDemo demo = new BizDemoImpl();
demo.helloGirl("Lucy");
BizDemo demoProxy = new BizDemoImplProxy(demo);
demoProxy.helloGirl("Lucy");
}
// 输入
LucyhelloGirl in BizDemoImpl
proxy by BizDemoImplProxy
LucyhelloGirl in BizDemoImpl
2. 用 java 动静代理生成类
-
- 首先让咱们忘掉对 BizDemoImpl 做代理,看看 java 主动生成代理类的成果
public class ProxyHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("proxy invoke." + args[0]);
return null;
}
}
能够看到,只有有 BizDemo 这个接口,就能够通过 java 动静代理生成一个类, 这个类领有接口 BizDemo 的所有办法,并且把所有办法调用,都透传到 ProxyHandler 的 invoke 办法中。
public static void main(String[] args) {Class[] inf = new Class[] {BizDemo.class};
BizDemo d = (BizDemo) Proxy.newProxyInstance(BizDemo.class.getClassLoader(), inf, new ProxyHandler());
d.helloGirl("javaDynamicProxy");
d.helloBoy("javaDynamicProxy boy");
}
// 输入
proxy invoke.javaDynamicProxy
proxy invoke.javaDynamicProxy boy
只管咱们能够让 java 给咱们动静生成一个类,这个类实现了 BizDemo 接口,然而这样的类没有太多的实际意义。咱们的目标是代理 BizDemoImpl,看看咱们是怎么达到的
-
- 让代理产生实际意义,对 BizDemoImpl 做代理
其实很简略,咱们只有把 BizDemoImpl 实例塞到 ProxyHandler 里,在 invoke 办法再调一次不就行了吗,于是咱们翻新创立一个 Handler: ProxyHandler1
- 让代理产生实际意义,对 BizDemoImpl 做代理
public class ProxyHandler1 implements InvocationHandler {
private BizDemo real;
public ProxyHandler1(BizDemo real) {this.real = real;}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("proxy invoke." + args[0]);
if (method.getName().equals("helloBoy")) {this.real.helloBoy((String)args[0]);
} else {this.real.helloGirl((String)args[0]);
}
return null;
}
}
public static void main(String[] args) {BizDemo demo = new BizDemoImpl();
Class[] inf = new Class[] {BizDemo.class};
BizDemo d = (BizDemo) Proxy.newProxyInstance(BizDemo.class.getClassLoader(), inf, new ProxyHandler1(demo));
d.helloGirl("javaDynamicProxy");
d.helloBoy("javaDynamicProxy boy");
}
// 输入
proxy invoke.javaDynamicProxy
javaDynamicProxyhelloGirl in BizDemoImpl
proxy invoke.javaDynamicProxy boy
javaDynamicProxy boyhelloBoy in BizDemoImpl
能够看到,动静代理生成的类,真正的代理了 BizDemoImpl 实例 demo
单从上述例子看,用 java 动静代理,反而更简单类,要引入 InvocationHandler 和 java.lang.reflect.Proxy, 但认真想是有益处的,
第一,不论用户的 interface 有多少个办法,最终都代理收拢到 InvocationHandler 的 invoke
第二,如果我的项目有很多 interface 要代理,代理类会成倍增加,难以保护
java 动静代理类图如下,
$Proxxy0 是 java 动静生成的类,这个类继承类 Proxy 实现了 BizDemo 接口,也就是上述的 main 中的 d,对 d 的调用,先到 $Proxy0, $Proxxy0 委托给父类的 Proxy 的成员变量 InvocationHandler 实例,即 ProxyHandler1 实例; 而 ProxyHandler1 实例的 invoke 办法里最终调用了被代理的 BizDemoImpl。
总之看起来很绕,框架类的代码往往就义直观来实现通用和简洁
正文完