zoukankan      html  css  js  c++  java
  • java代理的实现

    Java代理的实现

    静态代理

    一个接口,两个实现类,代理实现类组合真实实现类

    静态代理,是一种根据上面的理论,很自然会想到的一种不依赖于其他技术的代理模式实现方式。

    接口(动态代理也是该接口)

    public interface Work {
        void doWork();
    }
    

    目标类(动态代理也是该目标类)

    public class WorkImpl implements Work  {
        @Override
        public void doWork() {
            System.out.println("开始工作了");
        }
    }
    

    委托类

    public class WorkProxy implements Work{
    
        private Work work;
    
        public WorkProxy(Work work){
            this.work = work;
        }
        @Override
        public void doWork() {
            //执行前操作
            System.out.println("开始工作前");
            work.doWork();
            //执行后操作
            System.out.println("开始工作后");
        }
    }
    

    测试类

    public class WorkTest {
        public static void main(String[] args) {
            WorkImpl workImpl = new WorkImpl();
            Work work = new WorkProxy(workImpl);
            work.doWork();
        }
    }
    

    如果使用过静态代理,那么很容易理解,静态代理存在的缺陷。

    因此,也就出现了动态代理。

    动态代理的动态, 就是可以动态的切换真实实现类, 也就是说可以一个代理类(相同的代码, 相同的增强操作)应对一堆不确定的真实实现类.

    g1fLDg.png

    动态代理

    JDK动态代理

    jdk动态代理目标类必须要实现接口

    通过java.lang.reflect.Proxy类实现。

    动态代理就是为了解决静态代理不灵活的缺陷而产生的。静态代理是固定的,一旦确定了代码,如果委托类新增一个方法,而这个方法又需要增强,那么就必须在代理类里重写一个带增强的方法。而动态代理可以灵活替换代理方法,动态就是体现在这里。

    委托类

    public class Invocation implements InvocationHandler {
        /**
         * 实际目标类
         */
        Object realObject;
    
        public Invocation(Object realObject){
            this.realObject = realObject;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("工作前");
            Object invoke = method.invoke(realObject, args);
            System.out.println("工作后");
            return invoke;
        }
    }
    

    测试类

    /**
     * jdk原生动态代理
     * 目标类必须要实现接口
     */
    public class WorkTest {
        public static void main(String[] args) {
            WorkImpl work = new WorkImpl();
            Class<? extends WorkImpl> workClass = work.getClass();
            Work o = (Work) Proxy.newProxyInstance(workClass.getClassLoader(), workClass.getInterfaces(), new Invocation(work));
            o.doWork();
        }
    }
    

    CGLib动态代理

    CGLib动态代理是一个第三方实现的动态代理类库,不要求被代理类必须实现接口,它采用的是继承被代理类,使用其子类的方式,弥补了被代理类没有接口的不足。

    委托类

    public class Interceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object realObject, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("工作前");
            Object result = methodProxy.invokeSuper(realObject, objects);//目标类和方法调用的参数
            System.out.println("工作后");
            return result;
        }
    }
    

    测试类

    /**
     * CGLib 编译时增强
     * 会生成目标类的子类作为代理类
     */
    public class WorkTest {
        public static void main(String[] args) {
            //在指定目录下生成动态代理类,我们可以反编译看一下里面到底是一些什么东西
            String path = WorkTest.class.getResource("/").toString();
            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,
                    path.substring(path.indexOf("/") + 1));
            Enhancer enhancer = new Enhancer();
            //设置目标类
            enhancer.setSuperclass(WorkImpl.class);
            //设置拦截器
            enhancer.setCallback(new Interceptor());
            //生成代理类
            Work work = (Work) enhancer.create();
            work.doWork();
        }
    }
    
    

    Enhancer

    Enhancer指定要代理的目标对象。通过create方法得到代理对象。通过代理实例调用非final方法,方法调用请求会首先转发给MethodInterceptor的intercept

    MethodInterceptor

    通过代理实例调用方法,调用请求都会转发给intercept方法进行增强。

    反编译查看增强的文件

     public final void doWork() {
            MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }
    
            if (var10000 != null) {
                var10000.intercept(this, CGLIB$doWork$0$Method, CGLIB$emptyArgs, CGLIB$doWork$0$Proxy);
            } else {
                super.doWork();
            }
        }
    
    
  • 相关阅读:
    Leetcode665.Non-decreasing Array非递减数组
    在MyEclipse中把多行代码用一快捷键注释掉
    struts2中addFieldError()方法
    [bzoj2588][Spoj10628]Count on a tree_主席树
    [bzoj3123][Sdoi2013]森林_主席树_启发式合并
    [bzoj1500][NOI2005]维修数列_非旋转Treap
    [bzoj1452][JSOI2009]Count_树状数组
    [bzoj1369][Baltic2003]Gem_树形dp_结论题
    [bzoj1195][HNOI2006]最短母串_动态规划_状压dp
    [bzoj2242][Sdoi2011]计算器_exgcd_BSGS
  • 原文地址:https://www.cnblogs.com/huisunan/p/14738439.html
Copyright © 2011-2022 走看看