设计模式之代理模式
什么是代理模式
为其他对象提供一种代理以控制对这个对象的访问的一种设计模式。一张图解释代理模式: 文章正文图片
代理模式的优点
(1)隔离作用;(2)无侵入地进行某些业务逻辑的执行


代理模式的分类
两个大类:(1)静态代理; (2)动态代理
此外,无论是静态代理还是动态代理都有基于接口实现和基于继承实现两类,动态代理典型的如JDK代理(基于接口)和Cglib代理(基于继承)


静态代理
缺点:代理的方法越多,重复的逻辑越多。假设代理目标对象有100个方法需要进行代理执行,那么代理类里面也必须进行这100个方法的委托,而如果这些方法前后需要插入的逻辑是一样的话,这样做就会有100段重复的代码,耗时耗力。
示例:

Subject接口:Subject.java
public interface Subject {

    void say();

}


RealSubject.java     (Subject实现类)
public class RealSubject implements Subject {
    @Override
    public void say() {
        System.out.println("hello world");
    }
}

Proxy.java     (基于接口,实现Subject接口)
public class Proxy implements Subject{

    private RealSubject target;

    public Proxy(RealSubject target) {
        this.target = target;
    }

    public void say() {
        System.out.println("静态代理开始");
        try {
            target.say();
        } catch (Exception e) {
            System.out.println("error : " + e.getMessage());
            throw e;
        } finally {
            System.out.println("静态代理结束");
        }
    }

}

SubjectPlus.java   (基于继承实现代理, 继承RealSubject)
public class SubjectPlus extends RealSubject {

    @Override
    public void say() {
        System.out.println("基于继承的静态代理---开始");
        super.say();
        System.out.println("基于继承的静态代理---结束");
    }
}

Main方法:Client.java
public class Client {
    public static void main(String[] args) {
        //基于接口
        Proxy proxy = new Proxy(new RealSubject());
        proxy.say();

        //基于继承, 通过继承RealSubject实现代理
        Subject subject = new SubjectPlus();
        subject.say();
    }
}

执行结果:
静态代理开始
hello world
静态代理结束
基于继承的静态代理---开始
hello world
基于继承的静态代理---结束



动态代理之JDK代理
JDK代理只能针对有接口的类的接口方法进行动态代理。由于接口里面是不能有private方法的,所以jdk也无法对private方法进行代理。Subject、RealSubject沿用上述类。
自定义类:JdkProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class JdkProxy implements InvocationHandler {

    private RealSubject target;

    public JdkProxy(RealSubject target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始 JDK 动态代理");
        Object result;
        try {
            result = method.invoke(target, args);
        } catch (Exception e) {
            System.out.println("error : " + e.getMessage());
            throw e;
        } finally {
            System.out.println("完成 JDK 动态代理");
        }
        return result;
    }
}

Main方法:Client.java
import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {
        Subject subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, new JdkProxy(new RealSubject()));
        subject.say();
    }
}

运行结果
开始 JDK 动态代理
hello world
完成 JDK 动态代理



动态代理之Cglib代理
注:需要导入Cglib的jar包,此外,Cglib依赖于Asm.jar,需要一并导入。如果报错说java.lang.ClassNotFoundException: org.objectweb.asm.Type就是应为没引入Asm包。
由于Cglib是基于继承来实现代理,所以无法对static、final类进行代理,也无法对private、static方法进行代理
DemoInterceptor.java     实现了MethodInterceptor接口
import java.lang.reflect.Method;

public class DemoInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib 动态代理开始");
        Object result;
        try {
            result = methodProxy.invokeSuper(o, objects);
        } catch (Exception e) {
            System.out.println("error : " + e.getMessage());
            throw e;
        } finally {
            System.out.println("cglib 动态代理完成");
        }
        return result;

    }
}

Client.java  通过Enhancer获取代理实例
import net.sf.cglib.proxy.Enhancer;

public class Client {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new DemoInterceptor());
        Subject subject = (Subject) enhancer.create();
        subject.say();
    }

}

执行结果:
cglib 动态代理开始
hello world
cglib 动态代理完成

 
It's
欢迎访问本站,欢迎留言、分享、点赞。愿您阅读愉快!
*转载请注明出处,严禁非法转载。
https://www.devsong.org
QQ留言 邮箱留言
头像
引用:
取消回复
提交
涂鸦
涂鸦
热门