当前位置 : 主页 > 编程语言 > java >

Java 中的代理详解

来源:互联网 收集:自由互联 发布时间:2022-06-23
​ 决定一个人的一生,以及整个命运的,只是一瞬之间 —— 歌德 Java 中的代理详解 1. 作用 代理模式就是是通过创建代理类的方式来进行服务的访问,代理类通常会持有一个被代理类


决定一个人的一生,以及整个命运的,只是一瞬之间 —— 歌德


Java 中的代理详解

1. 作用

    代理模式就是是通过创建代理类的方式来进行服务的访问,代理类通常会持有一个被代理类的对象,代理类不会自己实现真正服务,而是通过调用被代理类对象的相关方法来提供服务,所以其实我们调用的还是被代理类的服务。这么做的话有助于我们进行方法增强操作,我们可以在访问服务之前或者之后加一下我们需要进行的其他操作。【AOP的思想就是这个样子】

2. 静态代理

    静态代理是在编写代码的时候就已经把代理类写好了,所有的东西都已经固定了【从名字上就能看出来】

2.1 技术实现

    代理类和被代理类实现同一个接口

2.2 使用语法规则

    静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类

2.3 代理实现

public class JDKProxyTest {
public static void main(String[] args) {
Person person = new Person("123123123");
YDTelephoneChargesProxy proxy = new YDTelephoneChargesProxy(person);
proxy.phoneMoney();
}
}

// 定义一个交话费的接口
interface TelephoneCharges {
void phoneMoney();
}

// 人们实现具体的交话费动作
class Person implements TelephoneCharges {

private String phoneNumber;

public Person(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

// 具体交话费的动作
@Override
public void phoneMoney() {
System.out.println("交话费执行动作");
}
}

/**
* 移动代理类,也实现了 TelephoneCharges 接口,保存一个交话费被代理对象,
* 这样既可以代理人们交话费
*/
class YDTelephoneChargesProxy implements TelephoneCharges {
// 被代理对象
Person person;

public YDTelephoneChargesProxy(Person person) {
// 只代理Person对象
if (person.getClass() == Person.class) {
this.person = person;
}
}

@Override
public void phoneMoney() {
// 方法前执行的操作
System.out.println("移动代理人们交话费");
// 被代理对象的方法
person.phoneMoney();
// 方法后执行的操作
System.out.println("移动代理人们交完话费");
}
}

2.4 运行结果

Java 中的代理详解_后端

2.5 小结

    其实代理模式我觉得核心思想就是方法增强操作,在方法的前后可以进行添加方法操作,这样在执行代理对象的时候可以进行一些其他方法的执行

3. 动态代理

    静态代理的例子中,代理类是自己定义好的,在程序运行之前就已经编译完成。动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码动态生成的。相比于静态代理动态代理的优势在于可以方便的对代理类的函数进行统一的操作处理,而不需要进行修改每个代理类中的方法

3.1 技术实现

    JDK 动态代理是由拦截器和反射技术来实现的

3.2 使用语法规则

  • 必须实现InvocationHandler接口
  • 使用Proxy.newProxyInstance产生代理对象
  • 被代理对象必须要实现接口
  • 3.3 实现步骤

  • 通过实现InvocationHandler接口来自定义自己的InvocationHandler
  • 通过Proxy.getProxyClass()获得动态代理类
  • 通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)
  • 通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入
  • 通过代理对象调用目标方法
  • 3.4 代码实现

    public class JDKProxyTest {
    public static void main(String[] args) {
    // 创建一个实例对象,这个对象是被代理的对象
    TelephoneCharges person = new Person("123123123");
    // 创建一个与代理对象相关联的InvocationHandler
    PhoneInvocationHandler<TelephoneCharges> handler =
    new PhoneInvocationHandler<>(person);
    // 创建一个代理对象 instance 来代理 person,代理对象
    // 的每个执行方法都会替换执行Invocation中的invoke方法
    TelephoneCharges instance = (TelephoneCharges) Proxy
    .newProxyInstance(TelephoneCharges.class.getClassLoader(),
    new Class<?>[]{TelephoneCharges.class}, handler);
    //代理执行上交话费的方法
    instance.phoneMoney();
    }
    }

    // 定义一个交话费的接口
    interface TelephoneCharges {
    void phoneMoney();
    }

    // 人们实现具体的交话费动作
    class Person implements TelephoneCharges {

    private String phoneNumber;

    public Person(String phoneNumber) {
    this.phoneNumber = phoneNumber;
    }

    // 具体交话费的动作
    @Override
    public void phoneMoney() {
    System.out.println("交话费执行的真正动作");
    }
    }

    class PhoneInvocationHandler<T> implements InvocationHandler {
    T target;

    public PhoneInvocationHandler(T target) {
    this.target = target;
    }

    /**
    * proxy:代表动态代理对象
    * method:代表正在执行的方法
    * args:代表调用目标方法时传入的实参
    */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("代理类执行方法 : " + method.getName());
    // 方法增强
    System.out.println("方法执行前逻辑处理");
    Object res = method.invoke(target, args);
    System.out.println("方法执行后逻辑处理");
    return res;
    }
    }

    3.5 运行结果

    Java 中的代理详解_Java_02

    3.6 小结

        动态代理的有点在于可以方便的对代理类的函数进行统一的处理,不需要修改每个代理类中的方法。这是因为所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以我们只要在invoke方法中进行统一的处理,就可以对所有被代理的方法进行方法增强操作了

    【文章原创作者:高防ip http://www.558idc.com/gfip.html欢迎留下您的宝贵建议】
    网友评论