Java 静态代理和动态代理

逆流者 2021年02月28日 73次浏览

静态代理

定义一个接口

public interface Operate {

    void sayHello();
}

接口实现类

public class OperateImpl implements Operate{
    @Override
    public void sayHello() {
        System.out.println("Hello...");
    }
}

代理类

public class OperatorProxy implements Operate{

    private OperateImpl operateImpl = null;

    @Override
    public void sayHello() {
        beforeSayHello();
        if(operateImpl == null){
            operateImpl =  new OperateImpl();
        }
        operateImpl.sayHello();
        afterSayHello();
    }

    private void beforeSayHello() {
        System.out.println("before sayHello");
    }

    private void afterSayHello() {
        System.out.println("after sayHello");
    }
}

测试静态代理

public class StaticProxyTest {

    public static void main(String[] args) {
        // 创建一个代理类
        Operate operate = new OperatorProxy();
        //代理者代替真实者做事情
        operate.sayHello();
    }
}

动态代理

JDK动态代理

定义接口

public interface Operate {

    void sayHello();
}

实现接口

public class OperateImpl implements Operate {
    @Override
    public void sayHello() {
        System.out.println("Hello...");
    }
}

动态代理绑定和代理逻辑的实现

public class JdkProxy implements InvocationHandler {

    //真实对象
    private Object target = null;

    /**
     * 建立代理对象和真实对象的代理关系,并返回代理对象
     * @param target 真实对象
     * @return 代理对象
     */
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 代理方法逻辑
     * @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("调度真实对象之前的服务");
        //相当于sayHelloWorld()
        Object obj = method.invoke(target, args);
        System.out.println("调度真实对象之后的服务");
        return obj;
    }

}

测试JDK动态代理

public class TestJdkProxy {

    public static void main(String[] args) {
        JdkProxy jdk = new JdkProxy();
        Operate proxy = (Operate) jdk.bind(new OperateImpl());
        proxy.sayHello();
    }
}

测试结果:

进入代理逻辑方法
调度真实对象之前的服务
Hello...
调度真实对象之后的服务

CGLIB动态代理

非抽象类:

package com.sinosoft.test.cglib;

/**
 * @author:Administrator
 * @date:2018/8/31
 * @describe:
 */
public class SayHelloImpl {
    public void sayHello(String name) {
        System.out.println("hello "+name);
    }
}

CGLIB 动态代理

package com.sinosoft.test.cglib;

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

import java.lang.reflect.Method;

/**
 * @author:Administrator
 * @date:2018/8/31
 * @describe: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.err.println("调用真实对象前....");
        //CGLIB 反射调用真实对象方法
        Object result = methodProxy.invokeSuper(proxy, args);
        System.err.println("调用真实对象后....");
        return result;
    }
}

测试 CGLIB 动态代理

package com.sinosoft.test.cglib;

/**
 * @author:Administrator
 * @date:2018/8/31
 * @describe:测试 CGLIB 动态代理
 */
public class TestCglibProxy {

    public static void main(String[] args) {
        CglibProxyExample cglib = new CglibProxyExample();
        SayHelloImpl proxyObj = (SayHelloImpl) cglib.getProxy(SayHelloImpl.class);
        proxyObj.sayHello("小明");
    }
}

测试结果:

调用真实对象前....
hello 小明
调用真实对象后....