动态代理Java实现

思考:在IBuyWatermelon添加一个方法selectWatermelon()

静态代理中需要在RealSubject中实现该方法,而且Proxy也要实现该方法调用RealSubject中的实现,如果再增加10个方法还是得这样操作,导致大量的代码重复。

现在来看动态代理(顾名思义,是在运行时才形成的代理对象,不像静态代理在编译时就载入代理对象)。

生成动态代理的方法有很多: JDK中自带的动态代理java.lang.reflect.*, CGlib等

下面的例子是JDK中自带的动态代理java.lang.reflect.*

IBuyWatermelon():接口

package com.maggie.dynamicproxy;

public interface IBuyWatermelon {
    //代理事件
    public abstract String buyWatermelon();
    
    public abstract void selectWatermelon();
}

BuyWatermelonImpl:实现类

package com.maggie.dynamicproxy;

//可理解成被代理者
public class BuyWatermelonImpl implements IBuyWatermelon {

    private Supermarket supermaket;
    
    public BuyWatermelonImpl(Supermarket supermaket) {
        super();
        this.supermaket = supermaket;
    }

    @Override
    public String buyWatermelon() {
        System.out.println("在"+supermaket.getName()+" 买西瓜");
        return "watermelon";
    }

    @Override
    public void selectWatermelon() {
        System.out.println("选择无籽西瓜");
    }

}

ProxyFactory:代理对象类(核心代码)

package com.maggie.dynamicproxy;

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

public class ProxyFactory {
     //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

   //给目标对象生成代理对象
    public Object getProxyInstance(){
        //动态代理的核心,涉及到反射
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //执行目标对象方法
                            Object returnValue = method.invoke(target, args);
                            return returnValue;
                    }
                }
        );
    }

}

客户端调用

package com.maggie.dynamicproxy;


public class Main {
    public static void main(String[] args) {
        Supermarket zhaoLiu = new Supermarket();
        zhaoLiu.setName("赵六超市");
        IBuyWatermelon target  = new BuyWatermelonImpl(zhaoLiu);//被代理的对象
        
        
        //创建代理对象
        IBuyWatermelon hourskeeper = (IBuyWatermelon) new ProxyFactory(target).getProxyInstance();
        
        hourskeeper.buyWatermelon();
        hourskeeper.selectWatermelon();
        
    }
}

输出

在赵六超市 买西瓜
选择无籽西瓜

现在就算IBuyWatermelon的方法再怎么增加,也只需要在BuyWatermelonImpl实现,就可以在客户端调用,不会出现大量的重复代码。

从静态代理到动态代理都围绕着卖瓜事件,为了前后方便比较,但是动态代理并没完,里面的源码机制才是核心关键

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)这个方法是整个动态代理实现的关键

原文地址:https://www.cnblogs.com/maggiejyt/p/7569123.html