关于动态代理的研究

来源:互联网 发布:身份证云终端软件 编辑:程序博客网 时间:2024/05/22 06:18

先说说代理模式,A类实现了某个功能,而出于某些原因,不能让别人直接调用A,需要B来代理A,那么就需要用到代理模式。代码大致如下:

public interface IFuncIntf {    public void func();}public class A implements IFuncIntf {    @Override    public void func() {    }}public class B implements IFuncIntf {    private A original;    @Override    public void func() {        original.func();    }}

这种在代码中新增代理类的方式为静态代理。而动态代理方式无需在代码中新增代理类,却能实现相同的功能,原因就在于动态代理会在程序运行时动态生成代理类。这里用Jdk自带的动态代理为例:

public class ProxyUtils {    public static <T> T proxyInstance(T object) {        return proxyInstance(object, null);    }    @SuppressWarnings("unchecked")    public static <T> T proxyInstance(T object, IProxyHandler handler) {        return (T) Proxy.newProxyInstance(object.getClass().getClassLoader(),                object.getClass().getInterfaces(), new DynamicProxy(object,                        handler));    }    public static interface IProxyHandler {        public void onPreCalled(Method method, Object[] args);        public void onPostCalled(Method method, Object[] args);    }    private static class DynamicProxy implements InvocationHandler {        private Object subject;        private IProxyHandler handler;        public DynamicProxy(Object subject, IProxyHandler handler) {            this.subject = subject;            this.handler = handler;        }        @Override        public Object invoke(Object object, Method method, Object[] args)                throws Throwable {            // TODO Auto-generated method stub            onPreCalled(method, args);            method.invoke(subject, args);            onPostCalled(method, args);            return null;        }        private void onPreCalled(Method method, Object[] args) {            if (handler != null) {                handler.onPreCalled(method, args);            }        }        private void onPostCalled(Method method, Object[] args) {            if (handler != null) {                handler.onPostCalled(method, args);            }        }    }}public static void main(String[] args) {        Subject realSubject = new RealSubject();        Subject subject = ProxyUtils.proxyInstance(realSubject, new ProxyUtils.IProxyHandler() {            @Override            public void onPreCalled(Method method, Object[] args) {                // TODO Auto-generated method stub                String text = args != null ? (String) args[0] : "";                System.out.println("onPreCalled " + method.getName() + ", " + text);            }            @Override            public void onPostCalled(Method method, Object[] args) {                // TODO Auto-generated method stub                String text = args != null ? (String) args[0] : "";                System.out.println("onPostCalled " + method.getName() + ", " + text);            }        });        subject.rent();        subject.hello("world");    }

读了一下源码,动态代理的原理很简单,传入原始对象和一组接口,会在运行期间动态生成一个类实现了这组接口,而接口中的所有实现调用都指向了我们传入的InvocationHandler,而这个InvocationHandler最终调用的还是我们的原始对象中的方法,只不过是通过method.invoke(object, args)方式,这里的object就是我们的原始对象,只不过所有的调用都是通过反射的方式。

动态代理还是很有用的,通常用于拦截或记录某个接口所有函数的调用,比如可以封装一层try catch,或在调用前后打日志,或做权限控制,或改变调用动作,根据条件实现分发等。插件框架中可以对插件的context接口使用使用这一技术,

0 0
原创粉丝点击