JDK代理模式(静态代理与动态代理)

代理模式

是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。

静态代理

        静态代理中代理类与被代理类都需要实现同一个接口,这就说明我们的一个静态代理类只能代理一个类,并且还要事先知道我们要代理哪个类才能写代理类,如果我们有其他类还想使用代理那就必须再写一个代理类。然而在实际开发中我们是可能是有非常多的类是需要被代理的,并且事先我们可能并不知道我们要代理哪个类。所以如果继续使用静态代理反而会增加许多的工作量,并且效率低下,代码复用率也不好。

举例:张三杀人案例

1、到法院打官司接口

package org.example.staticProxy;
/*
到法院打官司的接口
 */
public interface Court {
    public void doCourt();
}

2、律师代理类(实现打官司接口)

package org.example.staticProxy;
/*
律师代理类,代替(被代理类)被告打官司
实现打官司的接口
 */
public class Lawyer implements Court{
    //申明一个成员变量
    private Person person;

    //无参构造器
    public Lawyer() {
    }
    //有参构造器
    public Lawyer(Person person) {
        this.person = person;
    }
    //get方法
    public Person getPerson() {
        return person;
    }
    //set方法
    public void setPerson(Person person) {
        this.person = person;
    }
    //实现Court接口
    @Override
    public void doCourt() {
        System.out.println("律师取证:视频证明"+person.getName()+"张三当时正在旅游,不在案发现场");
        System.out.println("律师总结:张三不可能去杀人");
        person.doCourt();
    }
}

3、被代理类

package org.example.staticProxy;
/*
Person是被告,他要辩护
需要实现打官司的接口Court
 */
// 被代理的类
public class Person implements Court {
    private String name;
    //无参构造器
    public Person() {
    }
    //有参构造器
    public Person(String name) {
        this.name = name;
    }
    //get方法
    public String getName() {
        return name;
    }
    //set方法
    public void setName(String name) {
        this.name = name;
    }
    //实现Court接口
    @Override
    public void doCourt() {
        System.out.println(name + "说,我没有杀人");
    }
}

4、测试类

package org.example.staticProxyTest;

import org.example.staticProxy.Court;
import org.example.staticProxy.Lawyer;
import org.example.staticProxy.Person;
import org.junit.Test;

public class CourtTest {
    @Test
    public void Test1() throws Exception{
        Person p = new Person("李四");
        Court c = new Lawyer(p);
        c.doCourt();
    }
}

动态代理

        动态代理可以针对于一些不特定的类或者一些不特定的方法进行代理,我们可以在程序运行时动态的变化代理的规则,代理类在程序运行时才创建的代理模式成为动态代理。这种情况下,代理类并不是在Java代码中定义好的,而是在程序运行时根据我们的在Java代码中的“指示”动态生成的
      Proxy  动态代理 JDK动态代理         面向接口
      cglib    动态代理 第三方动态代理     面向父类

举例:吃饭

1、接口dinner

package org.example.dynamicProxy;

/*
吃饭的接口Dinner,有eat和drink两个抽象方法
 */
public interface Dinner {
    public void eat(String foodName);
    public void drink();
}

2、代理类person

package org.example.dynamicProxy;

public class Person implements Dinner{
    //申明一个成员变量
    private String name;
    //无参构造器
    public Person() {
    }
    //有参构造器
    public Person(String name) {
        this.name = name;
    }
    //get方法
    public String getName() {
        return name;
    }
    //set方法
    public void setName(String name) {
        this.name = name;
    }
    //类的实例化:创建对象
    @Override
    public void eat(String foodName) {
        System.out.println(name + "正在吃" + foodName);
    }
    //类的实例化:创建对象
    @Override
    public void drink() {
        System.out.println(name + "正在喝茶。");
    }
}

3、测试类

package org.example.dynamicProxyTest;

import org.example.dynamicProxy.Dinner;
import org.example.dynamicProxy.Person;
import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class eatTest {
    @Test
    public void eatTest() throws Exception{
        Dinner dinner = new Person("郑学浩");
        // 通过Porxy动态代理获得一个代理对象,在代理对象中,对某个方法进行增强
        // ClassLoader loader,被代理的对象的类加载器
        ClassLoader loader = dinner.getClass().getClassLoader();

        // Class<?>[] interfaces,被代理对象所实现的所有接口
        Class<?>[] interfaces = dinner.getClass().getInterfaces();

        // InvocationHandler h,执行处理器对象,专门用于定义增强的规则
        InvocationHandler handler = new InvocationHandler() {
            // invoke 当我们让代理对象调用任何方法时,都会触发invoke方法的执行
            // Object proxy, 代理对象
            // Method method,被代理的方法
            // Object[] args,被代理方法运行时的实参
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object res = null;

                if (method.getName().equals("eat")) {
                    System.out.println("饭前洗手");
                    // 让原有的eat的方法去运行
                    res = method.invoke(dinner,args);
                    System.out.println("饭后洗碗");
                }else{
                    // 如果是其他方法,那么正常执行就可以了
                    res = method.invoke(dinner,args);
                }

                return res;
            }
        };

        Dinner dinner1 = (Dinner) Proxy.newProxyInstance(loader, interfaces, handler);
        dinner1.eat("骡肉火烧");
        dinner1.drink();
    }

   
}

总结

在不修改原有代码的 或者没有办法修改原有代码的情况下  增强对象功能  使用代理对象 代替原来的对象去完成功能进而达到拓展功能的目的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小东很不戳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值