Java的代理proxy机制

2021-02-03

Java的代理proxy机制

代理必须分为两个步骤:
 * 1. 代理对象和真实对象建立代理关系
 * 2. 实现代理对象的代理逻辑方法

主要是通过两种方法:

1. JDK动态代理

JDK动态代理是java.lang.reflect.*包提供的方式,它必须借助一个接口才能产生代理对象,所以先定义接口。JDK动态代理中,要实现代理逻辑类必须去实现java.lang.reflect.InvocationHandler接口,

它里面定义了一个invoke方法,并提供接口数组用于下挂代理对象。

 

2. CGLIB动态代理

CGLIB动态代理,它的优势在于不需要提供接口,只要一个非抽象类就能实现动态代理。

但需要引入jar包或者 maven 的 pom.xml中添加:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

 

1. JDK动态代理

我们通过代码来看,主要包括4个java文件。

HelloWorld:测试文件接口
HelloWorldImpl:测试文件的实现
JdkProxyExample:实现代理
TestJdkProxy:测试代理

1) HelloWorld 测试文件接口

package cn.zc.javapro.mechanism.proxy.jdk;

public interface HelloWorld {
    public void sayHelloWorld();
}

2)HelloWorldImpl 测试文件的实现

package cn.zc.javapro.mechanism.proxy.jdk;

public class HelloWorldImpl implements HelloWorld {

    @Override
    public void sayHelloWorld() {
        System.out.println("Hello World!");
    }

}

3)JdkProxyExample:实现代理

package cn.zc.javapro.mechanism.proxy.jdk;

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

/*
 * 代理必须分为两个步骤:
 * 1. 代理对象和真实对象建立代理关系
 * 2. 实现代理对象的代理逻辑方法
 */

/*
 * JDK动态代理是java.lang.reflect.*包提供的方式,它必须借助一个接口才能产生代理对象,所以先定义接口。
 */

/*
 * JDK动态代理中,要实现代理逻辑类必须去实现java.lang.reflect.InvocationHandler接口,
 * 它里面定义了一个invoke方法,并提供接口数组用于下挂代理对象。
 */

public class JdkProxyExample implements InvocationHandler {

    //真实对象
    private Object target = null;
    
    /**
     * 1. 建立代理对象和真实对象的代理关系,并返回代理对象
     * @param target 真实对象
     * @return 代理对象
     */
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), this);
    }
    
    /**
     * 2.代理方法逻辑
     * @param proxy 代理对象
     * @param method 当前调度方法
     * @param args 当前方法参数
     * @return 代理结果返回
     * @throws Throwable 异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入代理逻辑方法");
        System.out.println("在调度真实对象之前的服务");
        Object obj = method.invoke(target, args); //相当于调用sayHelloWorld方法
        System.out.println("在调度真实对象之后的服务");
        return obj;
    }

}
JdkProxyExample

4)TestJdkProxy:测试代理

package cn.zc.javapro.mechanism.proxy.jdk;

public class TestJdkProxy {

    public static void main(String[] args) {
        JdkProxyExample jdk = new JdkProxyExample();
        //绑定关系,因为挂在接口HelloWorld下,所以声明代理对象HelloWorld proxy
        HelloWorld proxy = (HelloWorld)jdk.bind(new HelloWorldImpl());
        //注意,此时HelloWorld对象已经是一个代理对象,它会进入代理的逻辑方法invoke里
        proxy.sayHelloWorld();
        //相当于下面这段代码
        /*
        try {
            jdk.invoke(proxy, HelloWorldImpl.class.getMethod("sayHelloWorld", null), null);
        } catch (Throwable e) {
            e.printStackTrace();
        }*/
    }

}

2. CGLIB动态代理

我们通过代码来看,主要包括3个java文件。

HelloImpl:测试类

CglibProxyExample :代理实现类

TestCGLIBProxy:测试代理类

1)HelloImpl:测试类

package cn.zc.javapro.mechanism.proxy.cglib;

public class HelloImpl {
    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }
}

2)CglibProxyExample :代理实现类

package cn.zc.javapro.mechanism.proxy.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/*
 * 代理必须分为两个步骤:
 * 1. 代理对象和真实对象建立代理关系
 * 2. 实现代理对象的代理逻辑方法
 */
/*需要引入
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
*/
// CGLIB动态代理,它的优势在于不需要提供接口,只要一个非抽象类就能实现动态代理

public class CglibProxyExample implements MethodInterceptor {
    
    /**
     * 生成CGLIB代理对象
     * @param cls -- Class类
     * @return Class类的CGLIB代理对象
     */
    public Object getProxy(Class cls) {
        //CGLIB enhancer 增强类对象
        Enhancer enhancer = new Enhancer();
        // 设置增强类型
        enhancer.setSuperclass(cls);
        // 定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
        enhancer.setCallback(this);
        // 生成并返回代理对象
        return enhancer.create();
    }
    
    /**
     * 代理逻辑方法
     * @param proxy 代理对象
     * @param method 方法
     * @param args 方法参数
     * @param methodProxy 方法代理
     * @return 代理逻辑返回
     * @throws Throwable 异常
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("调用真实对象前");
        // CGLIB 反射调用真实对象方法
        Object result = methodProxy.invokeSuper(proxy, args);
        System.out.println("调用真实对象后");
        return result;
    }

}
CglibProxyExample

3)TestCGLIBProxy:测试代理类

package cn.zc.javapro.mechanism.proxy.cglib;

public class TestCGLIBProxy {

    public static void testCGLIBProxy() {
        CglibProxyExample cpe = new CglibProxyExample();
        HelloImpl obj = (HelloImpl)cpe.getProxy(HelloImpl.class);
        obj.sayHello("zhangsan");
    }
    
    public static void main(String[] args) {
        testCGLIBProxy();
    }

}

 

posted @ 2021-02-03 22:43  秦时明月0515  阅读(348)  评论(0编辑  收藏  举报