JDK静态代理和动态代理的代码实现

代理

  • 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象,在代理对象中调用目标对象,从而实现对目标对象的增强.
  • 代理模式:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的应为叫做Proxy或Surrogate,它是一种对象结构型模式。–《Java设计模式深入研究》

一 静态代理

  • JAVA静态代理的代理类在编译期就已经存在。
  • 静态代理:
    • 抽象主体角色:它的作用是定义一组行为规范。抽象角色一般呈现为接口(或抽象类),这些接口(或抽象类)中定义的方法就是待实现的。
    • 真实主体角色:实现接口所定义的方法。
    • 代理角色:实现目标类实现的相同接口中的方法,在代理类中调用目标类中的方法,实现对目标类的增强
  • 示例代码
定义接口(抽象主体角色)
public interface Subject {
    void helloWorld(String str);
}

接口实现类(真实主体角色)
public class SubjectImpl implements Subject {
    @Override
    public void helloWorld(String str) {
        System.out.println("hello World: "+str);
    }
}

代理类(代理角色)---需要和真实主体角色实现相同接口
public class SubjectImplProxy implements Subject {

    private SubjectImpl subject;

    public SubjectImplProxy(SubjectImpl object) {
        this.subject = object;
    }

    @Override
    public void helloWorld(String str) {
        System.out.println("----before----");
        subject.helloWorld(str);
        System.out.println("----after-----");
    }
}

调用
public static void main(String[] args) {
    Subject subject = new SubjectImplProxy(new SubjectImpl());
    subject.helloWorld("static");
}

调用结果
----before----
hello World: static
----after-----

  • 优缺点
    • 优点:调用方只需要知道代理类怎么实现(具体怎么调用委托类由代理类决定),不需要了解委托类怎么实现
    • 缺点:
      • 代理类和委托类实现了相同的接口,如果接口添加或者删除方法,委托类和代理类都要做出更改,后期维护会很复杂。
      • 代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。

二 动态代理

  • 动态代理是在运行期利用JVM的反射机制生成代理类
  • JDK的动态代理只能代理接口,代理类都需要实现InvocationHandler类,实现invoke方法。(如果需要代理没有实现接口的对象需要使用Cglib代理)
  • 实现动态代理需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类
    • java.lang.reflect.InvocationHandler
      • public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
        • Object proxy:方法在其上调用的代理实例
        • Method method:实例对应于在代理实例上调用的接口方法
        • Object[] args:在代理实例上的方法调用中传递的参数
    • java.lang.reflect.Proxy
      • public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h) throws IllegalArgumentException
        • ClassLoader loader:产生代理对象的类加载器
        • Class<?>[]interfaces:代理类实现的接口列表
        • InvocationHandler h:这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
  • 示例代码
public class MyInvocationHandler implements InvocationHandler {

    private Object targetObject;

    /**
     * 获取动态代理类
     * @param targetObject 目标对象
     * @return 生成的动态代理类实例
     */
    public Object newProxyInstance(Object targetObject) {
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
    }

    public MyInvocationHandler() {

    }

    public MyInvocationHandler(Object targetObject) {
        this.targetObject = targetObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("----before----");
        // 调用目标方法
        method.invoke(targetObject, args);
        System.out.println("----after----");
        return null;
    }
}

调用
public static void main(String[] args) {
    Subject subject = new SubjectImplProxy(new SubjectImpl());
    subject.helloWorld("static");

    System.out.println("-----------------------------------------------------------");

    MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
    Subject dynamicSubject = (Subject) myInvocationHandler.newProxyInstance(new SubjectImpl());
    System.out.println(dynamicSubject.getClass().getName());
    dynamicSubject.helloWorld("dynamic");
}

调用结果
----before----
hello World: static
----after-----
-----------------------------------------------------------
com.sun.proxy.$Proxy0
----before----
hello World: dynamic
----after----

  • 优点:和静态代理相比,动态代理可以代理多个类型的接口,复用性强,并且当目标对现象需要实现的方法比较多的时候,动态代理不需要像静态代理一样对每一个方法进行中转。

总结

  • jdk动态代理完全的实现了代理模式的设计理念,静态代理和动态代理用不同的方式生成了相同功能的代理类,只不过静态代理需要针对每一个目标对象创建不同的代理类,动态代理可以根据不同的目标对象动态的生成代理类更加的灵活。spring的aop就是基于代理实现的。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值