静态代理与动态代理

1、静态代理

  说白了就是代理类与目标类都去实现同一个接口,代理类实现方法时,会创建目标类对象。调用目标对象,并在在目标方法前后进行处理。        

        

  目标类(Dog):实现工共接口DogInterface,这样一来类Dog就需要实现里面的方法,

  代理类(DogProxy):也实现工共接口DogInterface,这样一来类DogProxy就需要实现里面的方法,再方法中调用Dog里面的实现方法并再其方法前后进行处理,便可做到增强的效果。

1.1、工共接口(DogInterface)

public interface DogInterface {

    void eat();

}

1.2、目标类(Dog)

public class Dog implements DogInterface{

    @Override
    public void eat() {
        System.out.println("小狗吃骨头!!!");
    }
    
}

1.3、代理类(DogProxy)

public class DogProxy implements DogInterface{
    
    // 创建目标对象
    private Dog dog;

    public DogProxy(Dog dog) {
        this.dog = dog;
    }

    @Override
    public void eat() {
        // 目标方法前置处理
        System.out.println("代理开始。。。。。");
        // 调用目标对象的方法
        dog.eat();
        // 目标方法后置处理
        System.out.println("代理结束。。。。。");
    }
}

1、4、测试类及运行结果

public class StaticTest {

    public static void main(String[] args) {
        Dog dog = new Dog();

        DogProxy dogProxy = new DogProxy(dog);

        dogProxy.eat();
    }

}
代理开始。。。。。
小狗吃骨头!!!
代理结束。。。。。

Process finished with exit code 0

1.5、静态代理的优缺点:

  • 优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展。
  • 缺点:
    • 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类。
    • 一旦接口增加方法,目标对象与代理对象都要维护。

 

2、JDK动态代理

  动态代理,例如基于接口的代理(JDK代理)。就不在需要去创建代理类,只需要一个代理工厂,可以处理任何类,任何方法的增强处理。

  • 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理。
  • 代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象。
  • 动态代理也叫做:JDK代理,接口代理。
  • 能在代码运行时动态的改变某个对象的代理,并且能为代理对象动态的增加方法、增加行为。

      

 

 

  这里只需要目标类(Dog)实现公共接口,并实现方法即可

2.1、工共接口(DogInterface)

public interface DogInterface {

    void eat();


    void run();
}

2.2、目标类(Dog)

public class Dog implements DogInterface {

    @Override
    public void eat() {
        System.out.println("小狗吃骨头!!!");
    }

    @Override
    public void run() {
        System.out.println("小狗跑起来!!!");
    }
}

2.3、代理工厂(ProxyFactory)

import java.lang.reflect.Proxy;

public class ProxyFactory {
    /**
     * 维护一个目标对象,Object
     */
    Object target;

    // 构造器,对目标对象进校初始化
    public ProxyFactory(Object target) {
        this.target = target;
    }

    /**
     * 给目标对象生成一个代理对象
     * @return 返回代理对象
     */
    public Object getProxyInstance() {
        // 参数说明
        // 1. loader
        /*
         * public static Object newProxyInstance(ClassLoader loader,
         *                                           Class<?>[] interfaces,
         *                                           InvocationHandler h)
         *  ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法固定
         *  Class<?>[] interfaces:目标对象实现的接口类型,使用泛型方法确定类型
         *  InvocationHandler h:事情处理,执行目标对象方法时,
         *                  会触发事件处理器方法,会把当前执行的目标对象方法作为一个参数传入
         */
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("JDK代理开始。。。。");
                    // 通过反射机制调用目标对象的方法
                    Object invoke = method.invoke(target, args);
                    System.out.println("代理结束。。。。。");
                    return invoke;
                });
    }
}

2.4、测试类及运行结果

public class JdkTest {

    public static void main(String[] args) {

        Dog dog = new Dog();

        DogInterface dogInterface = (DogInterface)new ProxyFactory(dog).getProxyInstance();

        System.out.println("代理类"+dogInterface.getClass());

        // 代理方法1
        dogInterface.eat();

        // 代理方法2
        dogInterface.run();
    }
}
代理类class com.sun.proxy.$Proxy0
JDK代理开始。。。。
小狗吃骨头!!!
代理结束。。。。。
JDK代理开始。。。。
小狗跑起来!!!
代理结束。。。。。

Process finished with exit code 0

 

posted @ 2022-09-14 19:18  编程小白1024  阅读(276)  评论(0编辑  收藏  举报