jdk Dynamic Proxy 动态代理

来源:互联网 发布:网络协议栈作用 编辑:程序博客网 时间:2024/05/08 03:37

说到动态代理,首先介绍下静态代理,静态代理是指首先有一组对外开放的接口,已知A类实现了此类接口,那么现在有一个代理类B同样实现了接口中的方法,这样在方法中调用被代理类A中相应的方法,在调用前后,可以加上一些处理代码,如日记记录,事务开启关闭等等。

而动态代理,关键一点就是动态,即将这种代理关系,延迟到jvm运行是来实现。相同需要一组对外接口,代理类实现InvocationHandler接口并实现其中的方法invoke(),然后用Proxy.newProxyInstance()创建代理类。

显然动态代理类有更好的灵活性,虽然为次而损失了一定的性能(其中存在大量的反射应用)。注意,代理的是接口不是类更不是抽象类。

应用:spring中的AOP。

下面是示例代码:

public interface WriteService {public void write();}public interface ReadService {//阅读public void read();}public class LearnServiceImpl implements ReadService,WriteService {@Overridepublic void read() {System.out.println("read()...");}@Overridepublic void write() {System.out.println("write()...");}}//动态代码类,实现InvocationHandlerpublic class DynamicProxy implements InvocationHandler {private Object target;public DynamicProxy(Object target) {this.target = target;}public Object createDynamicProxy() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before "+method.getName()+"()...");Object result = method.invoke(this.target, args);System.out.println("after "+method.getName()+"()...");return result;}}public class DynamicProxyDemo {public static void main(String[] args) {LearnServiceImpl ro = new LearnServiceImpl();ReadService proxy0 = (ReadService) new DynamicProxy(ro).createDynamicProxy();proxy0.read();System.out.println("代理对象:" + proxy0.getClass().getName());System.out.println("===========");WriteService proxy1 = (WriteService) new DynamicProxy(ro).createDynamicProxy();proxy1.write();System.out.println("代理对象:" + proxy1.getClass().getName());}}

动态代理可以在不改变原来已有代码结构的情况下,对原来“真实方法”进行扩展,增强其功能,并且可以达到控制被代理对象的行为
的目的。

运行结果:
before read()...
read()...
after read()...
代理对象:$Proxy0
===========
before write()...
write()...
after write()...
代理对象:$Proxy0

作为一个Dynamic Proxy,必须满足三个条件:
1.实现了InvocationHandler接口,实现接口中定义的invoke方法
2.包含接口实现类的实例

3.通过Proxy.newProxyInstance()方法Proxy与接口之间的绑定。

类图:



0 0