代理

114 阅读2分钟

静态代理和动态代理异同

  • 静态代理和动态代理,被代理的类和代理类都实现了相同的接口
  • 静态代理,代理类是在编译的时候就已经确认了的
  • 动态代理,代理类是在运行的时候通过被代理类动态生成的
  • 动态代理涉及到的类:Proxy.newProxyInstance、InvocationHandler

静态代理

package com.hhc.proxy;

/**
 * 功能描述
 *
 * @author hWX988311
 */
interface Sing {
    void sing();
}

/**
 * 被代理类:歌手
 */
class Singer implements Sing {

    @Override
    public void sing() {
        System.out.println("歌手在唱歌");
    }
}

/**
 * 代理类:经纪人
 */
class Broker implements Sing {
    private Sing sing;

    public Broker(Sing sing) {
        this.sing = sing;
    }

    @Override
    public void sing() {
        System.out.println("经纪人布置场景");
        sing.sing();
        System.out.println("经纪人收拾场景");
    }
}

public class StaticProxyTest {
    public static void main(String[] args) {
        Sing singer = new Singer();
        Sing broker = new Broker(singer);
        broker.sing();
    }
}

动态代理

package com.hhc.proxy;

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

/**
 * 功能描述
 *
 * @author hWX988311
 */
interface Human {
    void eat();
}

//代理类
class SuperMan implements Human {
    @Override
    public void eat() {
        System.out.println("超人喜欢吃甜甜圈");
    }
}

/**
 * 1. 生成代理类
 * 2. 在代理类中调用被代理类的方法
 */
class ProxyFactory {
    /**
     *
     * @param obj 被代理类实例
     * @return 返回代理类实例
     */
    public static Object getProxyInstance(Object obj) {
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }
}

class MyInvocationHandler implements InvocationHandler {
    private Object object;

    public void bind(Object object) {
        this.object = object;
    }

    /**
     * 调用代理类的方法时,会调用invoke方法
     *
     * @param proxy 代理类实例
     * @param method 被代理类实例方法
     * @param args 被代理类实例方法参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 对被代理方法进行增强: 调用被代理方法之前记录日志(开启事务)
        System.out.println("调用方法之前记录日志入参日志:" + args);

        //调用被代理类方法,需要一个被代理类实例对象, 返回被代理对象方法结果
        Object returnObject = method.invoke(object, args);

        // 对被代理方法进行增强: 调用被代理方法之前记录日志(关闭事务)
        System.out.println("调用方法之后记录日志出参日志:" + returnObject);
        return returnObject;
    }
}

public class ProxyTest {
    public static void main(String[] args) {
        // 创建被代理类
        Human human = new SuperMan();
        Human proxySuperMan = (Human) ProxyFactory.getProxyInstance(human);
        proxySuperMan.eat();

        // 创建代理类
        Sing sing = new Singer();
        Sing proxySinger = (Sing)ProxyFactory.getProxyInstance(sing);
        proxySinger.sing();
    }
}