欢迎访问宙启技术站
智能推送

Java动态代理模式怎么实现

发布时间:2023-05-17 03:10:33

动态代理是指在运行期间通过反射机制动态地生成代理类,从而实现对目标对象的调用;而静态代理则是在编译期间就已经生成好代理类,因此无法灵活地处理各种代理需求。

Java中的动态代理主要有两种实现方式:基于接口的动态代理和基于类的动态代理。

基于接口的动态代理

基于接口的动态代理主要利用Java的反射机制,实现动态创建符合指定接口的代理对象。

以下是基于接口的动态代理的实现步骤:

1. 创建InvocationHandler接口的实现类,该类负责实现invoke方法,在该方法中对目标方法进行增强处理。

2. 使用Proxy类的newProxyInstance方法创建代理对象。该方法有三个参数:ClassLoader loader、Class[] interfaces、InvocationHandler h。其中,ClassLoader loader一般指定目标对象的类加载器,Class[] interfaces指定目标对象所实现的接口,InvocationHandler h指定代理对象的业务处理逻辑。

下面是一个基于接口的动态代理实例:

public interface Subject {
    void request();
}

public class RealSubject implements Subject {
    public void request() {
        System.out.println("RealSubject's request method.");
    }
}

public class DynamicProxy implements InvocationHandler {
    private Object subject;

    public DynamicProxy(Object subject) {
        this.subject = subject;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        method.invoke(subject, args);
        System.out.println("after");
        return null;
    }
}

public class Client {
    public static void main(String[] args) {
        RealSubject rs = new RealSubject();
        InvocationHandler ih = new DynamicProxy(rs);
        ClassLoader cl = rs.getClass().getClassLoader();
        Subject subject = (Subject) Proxy.newProxyInstance(cl, rs.getClass().getInterfaces(), ih);
        subject.request();
    }
}

在该例子中,RealSubject是被代理的类,DynamicProxy是InvocationHandler的实现类,Client类是测试类。

基于类的动态代理

基于类的动态代理主要利用字节码生成技术,在运行期间动态创建代理类。

以下是基于类的动态代理的实现步骤:

1. 创建一个继承自Proxy的代理类,并重写其中的invoke方法,在该方法中对目标方法进行增强处理。

2. 使用字节码生成技术生成代理类的字节码,最后通过类加载器加载该字节码并生成代理对象。

下面是一个基于类的动态代理实例:

public class DynamicProxy extends Proxy {
    protected DynamicProxy(InvocationHandler h) {
        super(h);
    }

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
        try {
            // 生成代理类的字节码
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass("$Proxy0", interfaces);

            // 将字节码写入到文件中,可以查看生成的代理类的结构信息
            FileOutputStream out = new FileOutputStream("./$Proxy0.class");
            out.write(proxyClassFile);
            out.flush();
            out.close();

            // 加载代理类字节码并生成代理对象
            Class<?> proxyClass = defineClass(loader, proxyClassFile, 0, proxyClassFile.length);
            return proxyClass.getConstructor(InvocationHandler.class).newInstance(h);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class RealSubject {
    public void request() {
        System.out.println("RealSubject's request method.");
    }
}

public class DynamicProxyTest {
    public static void main(String[] args) {
        InvocationHandler ih = new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("before");
                Object result = method.invoke(new RealSubject(), args);
                System.out.println("after");
                return result;
            }
        };
        RealSubject subject = (RealSubject) DynamicProxy.newProxyInstance(DynamicProxyTest.class.getClassLoader(), new Class[]{RealSubject.class}, ih);
        subject.request();
    }
}

在该例子中,RealSubject是被代理的类,DynamicProxy是代理类的实现类,DynamicProxyTest是测试类。通过代理类的字节码生成技术,动态生成代理类,并通过类加载器加载代理类,并最终生成代理对象。