java静态代理、动态代理、cglib动态代理实现原理

什么是静态代理、动态代理

在面向对象编程时,经常会遇到一些需要统一处理的东西,比如每个方法的耗时打印、数据库的事物管理、以及一些其他的切面功能,这些功能如果加入到每个类里,就会有很多的重复代码,而且不便于维护。因此产生了代理对象,将这些需要统一处理的功能加入到代理对象中,统一由代理对象进行管理。
比如下面的一个图书类:

/**
 * 被代理对象接口
 */
public interface BookInterface {

    void add();

    void print();
}
/**
 * 被代理对象实现类
 */
public class BookInterfaceImpl  implements BookInterface{
    public void add() {
        System.out.println("add book!");
    }

    public void print() {
        System.out.println("print method");
    }
}

现在需要在每个方法前或者后增加一定的处理,通过静态代理、动态代理分别怎么实现?

静态代理

静态代理的实现方法是,通过新建一个代理对象实现被代理对象的接口,重写被代理对象的方法,加入增强处理;示例代码如下:

/**
 * 静态代理对象
 */
public class StaticPoxyBook implements BookInterface{

    //被代理对象
    private BookInterface target;

    public StaticPoxyBook(BookInterface target){
        this.target = target;
    }
    @Override
    public void add(){
        System.out.println("静态代理前处理");
        target.add();
    }

    @Override
    public void print() {
        System.out.println("静态代理前处理");
        target.print();
    }
}

测试代码

import org.junit.Before;
import org.junit.Test;

public class MainClass {
    BookInterface bookInterface ;
    @Before
    public void testBefore(){
        bookInterface = new BookInterfaceImpl();
    }

    @Test
    public void testStaticProxy(){
        //静态代理:通过初始化代理对象,调用代理对象的相同的方法,实现增强功能
        StaticPoxyBook staticPoxyBook = new StaticPoxyBook(bookInterface);
        staticPoxyBook.add();
    }
}

jdk动态代理

jdk动态代理是通过新建一个代理对象,在代理对象实现InvocationHandler接口,并重写invoke方法,实现增强处理

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


/**
 * jdk动态代理对象
 */
public class DynamicProxyBook implements InvocationHandler {

    Object target;

    public Object getInstance(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前处理");
        return method.invoke(target, args);
    }
}

测试代码(为了生成动态的class代理文件,这里用main方法测试)

 public static void main(String[] args) {
        BookInterface bookInterface = new BookInterfaceImpl();
        
        //生成$Proxy0的class文件(生成class路径在src同级目录下的com\sun里)
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        DynamicProxyBook dynamicProxyBook = new DynamicProxyBook();
        //动态代理:通过getInstance代理对象,调用代理接口,实现增强功能
        BookInterface bookInterfaceProxy = (BookInterface) dynamicProxyBook.getInstance(bookInterface);
        bookInterfaceProxy.add();
    }

动态代理生成的class文件,如下

package com.sun.proxy;

import com.proxy.test.BookInterface;

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


/**
 * 生成的代理对象和被代理对象实现同一接口
 * 拥有我们新建的代理对象的引用 paramInvocationHandler
 */
public final class $Proxy0 extends Proxy implements BookInterface {
    private static Method m1;
    private static Method m4;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler paramInvocationHandler) {
        super(paramInvocationHandler);
    }

    public final boolean equals(Object paramObject) {
        try {
            return ((Boolean) this.h.invoke(this, m1, new Object[]{paramObject})).booleanValue();
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }

    public final void print() {
        try {
            this.h.invoke(this, m4, null);
            return;
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }

    public final String toString() {
        try {
            return (String) this.h.invoke(this, m2, null);
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }

    /**
     * 调用方法时,实际调用的是我们新建的DynamicProxyBook的invoke方法
     */
    public final void add() {
        try {
            this.h.invoke(this, m3, null);
            return;
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }

    public final int hashCode() {
        try {
            return ((Integer) this.h.invoke(this, m0, null)).intValue();
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m4 = Class.forName("com.proxy.test.BookInterface").getMethod("print", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("com.proxy.test.BookInterface").getMethod("add", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        } catch (NoSuchMethodException localNoSuchMethodException) {
            throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        } catch (ClassNotFoundException localClassNotFoundException) {
            throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
    }
}

通过生成的class文件,可以知道jdk动态代理只能代理接口。

cglib动态代理

和jdk的类似,代理对象实现MethodInterceptor 接口,然后重写intercept方法,实现增强处理。

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

/**
 * cglib动态代理对象
 */
public class CglibDymicProxyBook implements MethodInterceptor {

    Object target;

    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib前处理");
        return  methodProxy.invokeSuper(o, objects);
    }
}

测试代码

 public static void main(String[] args) {
        BookInterface bookInterface = new BookInterfaceImpl();
        //生成代理的class文件
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D://code");
        CglibDymicProxyBook cglibDymicProxyBook = new CglibDymicProxyBook();
        //动态代理:通过getInstance代理对象,调用代理接口,实现增强功能
        BookInterface bookInterfaceProxy = (BookInterface) cglibDymicProxyBook.getInstance(bookInterface);
        bookInterfaceProxy.add();
    }

你可能感兴趣的:(java静态代理、动态代理、cglib动态代理实现原理)