Skip to content

动态代理

1.什么是动态代理

java
public class Student{
    public void eat(){
        system.out.println("吃饭");
    }
}

如果要给eat方法添加吃饭之前要拿筷子和盛饭的动作,一般来说只能在源代码中添加对应的功能。这属于侵入式修改,在成熟的项目中很少会这样修改,因为可能会产生bug。 此时可以利用代理来帮助我们做以上的两个准备工作再去执行原方法,这种方式叫做动态代理,其特点是能够无侵入式给代码增加额外的功能。

2.程序为什么需要代理?

如果一个对象的功能过于繁杂,就可以通过代理处理多余的事务。如果对象有什么方法要被代理,那么代理就应该提供对应的方法。但是代理并不知道具体应该提供什么方法,就需要使用接口

例如,鸡哥需要代理实现唱歌、跳舞、打篮球的方法就应该这样定义接口:

java
public Interface Kun(){
    public void sing();
    public void dancing();
    public void playBasketball();
}

3.如何实现代理?

  1. 首先定义一个接口,创建要实现的功能。
java
public interface Star {
    String sing(String name);
}
  1. 然后被代理的对象实现接口的方法
java
public class BigStar implements Star{
    private String name;

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

    public String sing(String name){
        System.out.println(this.name + "正在唱" + name);
        return "谢谢大家!";
    }
}
  1. 创建一个代理类,定义一个创建代理方法代理上述对象, 这一步是动态代理的关键。
java
import java.lang.reflect.Proxy;

public class ProxyBigStar {
/**
 * 使用java.lang.reflect.Proxy.newProxyInstance提供为对象产生代理对象的方法。
 *
 * 1.参数一、用于指定哪个类加载器,加载生成的代理类
 * 2.指定接口,用于指定生成的代理的方法
 * 3.通过InvocationHandler来指定生成的代理对象要实现的功能
 */
    public static Star createProxy(BigStar bigStar){

        return (Star) Proxy.newProxyInstance(

            // 三个参数分别是:类加载器获取被代理的接口类、实现该接口的类的方法、调用该方法的实参
                ProxyBigStar.class.getClassLoader(),
                new Class[]{Star.class},
                (proxy, method, args) -> {
                    if ("sing".equals(method.getName())){
                        System.out.println("准备唱歌~");
                    } else if ("dancing".equals(method.getName())){
                        System.out.println("准备跳舞~");
                    }
                    return method.invoke(bigStar,args);
                }
        );
    }
}
  1. 最后一步是调用该代理实现被代理对象的方法
java
public class StarTest {
    public static void main(String[] args) {
        BigStar bigStar = new BigStar("鸡哥");
        Star proxy = ProxyBigStar.createProxy(bigStar);
        String res = proxy.sing("只因你太美!");
        System.out.println(res);
    }
}
  1. 输出

Alt text

Released under the MIT License.