代理模式之动态代理之一JDK动态代理

1、代理模式概念
为一个对象提供一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象。
好处:可在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
被代理的对象包括:远程对象、创建开销大的对象或需要安全控制的对象。

2、代理模式分类

  1. 静态代理;
  2. 动态代理:jdk代理(又称接口代理)、cglib代理(可在内存动态的创建对象,而不需要实现接口,属于动态代理范畴)。

3、动态代理之jdk代理介绍

  1. 代理对象不需要实现接口;目标对象需实现接口,否则不能使用jdk代理。
  2. 代理对象的生成,利用jdk的api,动态在内存中构建代理对象。

原理:反射生成代理类。

实现步骤:
1)、业务接口;
2)、业务接口的实现类;即目标对象;
3)、代理对象类须实现InvocationHandler接口(因在获取代理对象时需要InvocationHandler对象)及在获取代理对象的Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this)方法:- 核心类
1.须实现一个invoke()方法,该方法实现业务;2.需要建一个目标初始化的方法。

4、UML类图
在这里插入图片描述

5、注意事项

  1. 代理类所在包java.lang.reflect.proxy;
  2. jdk实现代理只需使用newProxyInstance()方法,其三个参数,第一个参数:目标的装载器;第二个参数:获取代理类实现的所有接口,为每个接口生成代理;第三个参数:调用实现了InvocationHandler的对象,当你一调用代理,代理就会调用InvocationHandler的invoke方法

6、优缺点
优点:

  1. 一个动态代理类更加简单了,可以解决创建多个静态代理的麻烦,避免不断的重复多余的代码;
  2. 调用目标代码时,会在方法“运行时”动态的加入,决定你是什么类型,才调谁,灵活。

缺点:

  1. 系统灵活了,但是相比而言,效率降低了,比静态代理慢一点(静态代理在编译时指定更明确谁调用谁,稍微快一点点吧);
  2. 动态代理比静态代理在代码的可读性上差了一点,不太容易理解。

7、jdk动态代理和cglib动态代理的区别:

  1. jdk动态代理是需要有接口类;cglib动态代理不需要有接口类;

8、demo
接口类

package com.model.proxy.jdkproxy;
/**
 * 接口
 */
public interface Person {
    boolean addPerson(String name);
}

目标对象 - 接口实现类

package com.model.proxy.jdkproxy;
/**
 * 目标对象,即被代理对象
 */
public class TeacherTarget implements Person {
    @Override
    public boolean addPerson(String name) {
        System.out.println("添加 = " + name + " 成功");
        return true;
    }
}

动态代理类

package com.model.proxy.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory implements InvocationHandler {
    // 被代理对象,即目标对象
    private Object target;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    /**
     * 获取代理对象
     *
     * newProxyInstance()方法参数说明:
     * 1、第一个参数ClassLoader:当前目标对象的类载器
     * 2、第二个参数Class<?>[]:当前目标对象实现的接口类型,使用泛型方法确认类型。获取代理类实现的所有接口,为每个接口生成代理
     * 3、第三个参数InvocationHandler:调用实现了InvocationHandler的对象,一调用代理,代理就会调用InvocationHandler的invoke方法
     * 事情处理,执行目标对象的方法时,会触发事情处理器的方法,把当前执行的目标对象方法作为参数传入
     *
     */
    public Object getProxyObject() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("jdk proxy start...");
        logging(); // 在代理目标方法执行前加入日志记录
        // 通过反射机制,调用目标对象的方法
        Object object = method.invoke(target, args);
        System.out.println(target.getClass());
        System.out.println(args[0]);
        System.out.println(object.getClass());
        return object;
    }

    private void logging() {
        System.out.println("logging...");
    }
}

测试

package com.model.proxy.jdkproxy;

/**
 * 动态代理模式之jdk代理demo
 *
 * 实现步骤:
 * 1、业务接口;
 * 2、业务接口的实现类;即目标对象;
 * 3、代理对象类须实现InvocationHandler接口(因在获取代理对象时需要InvocationHandler对象)
 *  及在获取代理对象的Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this)方法:- 核心类
 *  1.须实现一个invoke()方法,该方法实现业务;2.需要建一个目标初始化的方法。
 */
public class Main {
    public static void main(String[] args) {
        // 获取代理对象
        Person target = (Person) new ProxyFactory(new TeacherTarget()).getProxyObject();
        System.out.println("target class = " + target.getClass());

        // 通过代理对象调用相应方法
        target.addPerson("hello");
    }
}

结果输出

target class = class com.sun.proxy.$Proxy0
jdk proxy start...
logging...
添加 = hello 成功
class com.model.proxy.jdkproxy.TeacherTarget
hello
class java.lang.Boolean
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值