zoukankan      html  css  js  c++  java
  • 代理模式(静态代理、动态代理)

    代理模式的由来:当调用某个对象时,不关心是否准确得到该对象,而是只要一个能提供对应功能的对象即可,这时我们可以为该对象提供一个代理对象,由代理对象控制对源对象的引用。

    第一.静态代理

    常见静态代理模式:一个接口,两个实现类,分别为被代理类和代理类,代理类中进行如下操作即可
    1.创建接口类型成员变量
    2.构造方法中创建被代理类对象()
    3.实现的接口方法中调用被代理类的实现的接口方法
    示例代码如下:

    // 被代理类
    class SubjectImpl implements Subject {
        @Override
        public void action() {
            System.out.println("执行action方法体");
        }
    }
    
    // 代理类
    class ProxyClass implements Subject {
        private Subject subject = new SubjectImpl();
    
        private void beforeHandle() {
            System.out.println("业务方法执行前执行前置增强处理");
        }
    
        private void afterHandle() {
            System.out.println("业务方法执行后执行后置增强处理");
        }
    
        @Override
        public void action() {
            this.beforeHandle();
            subject.action();
            this.afterHandle();
        }
    
    }
    
    public class ProxyTest {
        public static void main(String[] args) {
            ProxyClass obj = new ProxyClass();
            obj.action();
        }
    }

    要使用被代理类对象的方法时,只需简单的实例化代理类对象,调用此代理类对象的方法即可,其实是方法内部调用了被代理类的方法。

    第二.动态代理

    JDK动态代理主要用到了Proxy类和InvocationHandler接口,两者都在java.lang.reflect包下。

    首先介绍一下Proxy类,这个类是所有动态代理类的父类,主要用到这个类的newProxyInstance()静态方法:

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

    这个方法直接生成一个动态代理类对象,方法需要传三个参数,第一个参数是被代理类对应的类加载器对象,第二个参数是被代理类实现的一系列接口对应的Class对象组成的数组一个数组,第三个参数是一个InvocationHandler对象(一个InvocationHandler实现类对象)。

    InvocationHander接口就只有一个方法:

    public Object invoke(Object proxy, Method method, Object[] args)

    我们得自定义一个InvocationHander接口实现类,重写invoke()方法。

    JDK动态代理代码示例:

    //接口
    interface Subject {
        public void doSomething(String str);
    }
    
    // 接口实现类
    class RealSubject implements Subject {
        @Override
        public void doSomething(String str) {
            System.out.println("Subject接口实现类RealSubject实现doSomething方法()");
        }
    }
    
    // InvocationHandler接口实现类
    class MyIncovationHandler implements InvocationHandler {
        private Object proxied;
    
        // 构造器参数是被代理类对象
        public MyIncovationHandler(Object proxied) {
            this.proxied = proxied;
        }
    
        public MyIncovationHandler() {
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            method.invoke(proxied, args);
            after();
            return null;
        }
    
        // 增强处理方法,可以抽出到一个单独的工具类里面
        private void before() {
            System.out.println("Before处理");
        }
    
        private void after() {
            System.out.println("After处理");
        }
    }
    
    public class JdkDynamicProxyTest {
        public static void main(String args[]) {
            Subject s = new RealSubject();
            Object obj = Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(),
                    new MyIncovationHandler(s));
            Subject subject = (Subject) obj;
            subject.doSomething("kou");
        }
    }

         上例中,有一个RealSubject类,实现了接口Subject。InvocationHander接口的实现类MyInvocationHander,重写了invoke方法,在方法体中调用第二个参数method的invoke方法,method的invoke方法需要两个参数,第一个参数是被代理类的实例,第二个参数是参数列表,是invoke方法的第三个参数。这里被代理类的实例不建议直接new出来一个实例然后传进去,而是建议在创建InvocationHander实例时把被代理类实例传进来,这样比较解耦。

          编译上Proxy.newProxyInstance()的返回值类型是Object,但其实运行时类型是动态代理类的类型($Proxy开头的类),又因为实现了代理类所实现的全部接口,所以可以强转为任意一个所实现的接口类型。这个时候调用该接口的方法,底层就会执行接口实现类对应的实现。

          Proxy的newProxyInstance()方法的第二个参数是接口对应的Class对象组成的数组,而不是被代理类的Class对象。所以说,JDK动态代理建立在接口之上的。那么,如果被代理类没有实现任何接口,就不能用JDK动态代理了,需要用到cglib动态代理。cglib动态代理其实是对被代理类创建一个子类,让这个子类去代理父类,所以要求被代理类不能是final的。

  • 相关阅读:
    my first android test
    VVVVVVVVVV
    my first android test
    my first android test
    my first android test
    ini文件
    ZZZZ
    Standard Exception Classes in Python 1.5
    Python Module of the Week Python Module of the Week
    my first android test
  • 原文地址:https://www.cnblogs.com/koushr/p/5873447.html
Copyright © 2011-2022 走看看