java动态代理实现

  1. 静态代理
  2. 动态代理

image-20240617220235009

静态代理

静态代理主要由一个公共接口,一个具体的类,一个代理类组成。代理类持有具体类的实例。代理的是具体类的实例方法。

公共接口:

public interface Person {
    // 上交班费
    void giveMoney();
}

具体类:

public class Student implements Person {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    @Override
    public void giveMoney() {
        System.out.println(name + "上交班费50元");
    }
}

代理类:

public class StudentsProxy implements Person {
    Student stu;

    public StudentsProxy(Person stu) {
        // 只代理学生对象
        if (stu.getClass() == Student.class) {
            this.stu = (Student) stu;
        }
    }

    @Override
    public void giveMoney() {
        stu.giveMoney();
    }
}

为什么要用代理类去调用具体类的方法?引入这种间接性的好处?

不直接调用实际对象的方法,我们在代理过程中就可以加上一些其他用途。比如,在上交班费前记录下。

public class StudentsProxy implements Person {
    Student stu;

    public StudentsProxy(Person stu) {
        // 只代理学生对象
        if (stu.getClass() == Student.class) {
            this.stu = (Student) stu;
        }
    }

    @Override
    public void giveMoney() {
        System.out.println(stu.getName() + "学习上有很大进步");
        stu.giveMoney();
    }
}

然而静态定理只实现了对特定类的代理,如这里只实现了对Student类的代理,如果还有其他的类呢,都要写一个代理类?而且在多个实现类中如果都要记录下日志,对每个实现类都要多写个日志代码,显得很冗余,且业务逻辑与日志没有解耦,于是动态代理就是解决这个问题。

动态代理

在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。

接口与具体类与静态代理相同

代理类

public class StuInvocationHandler<T> implements InvocationHandler {
    // 代理对象
    T target;
    public StuInvocationHandler(T target) {
        this.target = target;
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clazz){
        //创建代理对象
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");
        Object result = method.invoke(target, args);
        return result;
    }
}

测试

public class ProxyTest {
    public static void main(String[] args) {
        Student wdcp = new Student("wdcp");
        StuInvocationHandler<Person> stuInvocationHandler = new StuInvocationHandler<Person>(wdcp);
        // 创建代理对象
        Person stuProxy = stuInvocationHandler.getProxy(Person.class);
        stuProxy.giveMoney();
    }
}

如此一来,就可以解决上面静态代理的两个问题:

1、不必为每个实现类编写一个代理类,通过泛型动态创建具体类的代理对象。

2、当多个实现类中都需要添加日志或者其他信息时,不需要在每个实现类中添加,在invoke方法中添加一条后即可。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1216271933@qq.com

×

喜欢就点赞,疼爱就打赏