java 中的动态代理实现

1. 什么是代理模式

代理模式是常见的设计模式之一,顾名思义,代理模式就是代理对象具备真实对象的功能,并代替真实对象完成相应操作,并能够在操作执行的前后,对操作进行增强处理。(为真实对象提供代理,然后供其他对象通过代理访问真实对象)。

代理就是帮别人做事情,如:工厂的中介,中介负责为工厂招收工人,那么中介就是工厂的代理;客户通过商家购买东西,商家向厂家购买货物,商家就是工厂的代理 。

在开发中存在a类需要调用c类的方法,完成某一个功能,但是c禁止a调用。这时,可以在a和c之间创建一个b类代理,a类访问b类,b类访问c类。

代理模式就是为其他对象提供一种代理来控制这个对象的访问,在某些情况下一个对象不适合或不能直接引用另一个对象,而代理对象可以在客户类和目标对象直接起到中介的作用
 

代理有分为动态代理和静态代理

2. 什么是静态代理

由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成.

 缺点: 

1. 被代理对象增加,代理对象也要增加,导致代理数量过多

2. 被代理对象接口如有改动,其实现类都需要改动

/**
 * 订单接口类
 */
public interface OrderService {
    void save();
}
/**
 * 订单实现类
 */
public class OrderServiceImpl implements OrderService{

    @Override
    public void save() {
        System.out.println("保存订单信息 ...");
    }
}
/**
 * 代理对象
 */
public class ProxyOrderService implements OrderService {

    // 被代理的对象
    private OrderService orderService;

    public ProxyOrderService(OrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public void save() {
        System.out.println("代理前置处理 ...");
        // 执行被代理的对象的方法
        orderService.save();
        System.out.println("代理后置处理 ...");
    }
}
    // 执行
    public static void main(String[] args) {
        // 创建被代理对象
        OrderService orderService = new OrderServiceImpl();

        // 创建代理对象
        ProxyOrderService proxy = new ProxyOrderService(orderService);

        proxy.save();
    }

输出

2. 什么是动态代理

代理类在程序运行时创建的代理方式被成为动态代理。 我们上面静态代理的例子中,代理类(ProxyOrderService )是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。

jdk 动态代理

/**
 * 订单接口类
 */
public interface OrderService {
    void save();
}


/**
 * 订单实现类
 */
public class OrderServiceImpl implements OrderService{

    @Override
    public void save() {
        System.out.println("保存订单信息 ...");
    }
}
/**
 *
 * 代理对象 实现 InvocationHandler
 * InvocationHandler 该类做方法拦截所用, 通过此类可以对目标方法进行增强
 */
public class ProxyOrderService implements InvocationHandler {

    private OrderService orderService;

    public ProxyOrderService(OrderService orderService) {
        this.orderService = orderService;
    }

    /**
     * 通过该方法的调用对目标对象进行增强
     * @param proxy  代理类代理的真实代理对象
     * @param method 执行的方法
     * @param args   执行方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理前置处理 ...");
        Object invoke = method.invoke(orderService, args);
        System.out.println("代理后置处理 ...");

        return invoke;
    }

    /**
     * ClassLoader loader   类加载器
     * Class<?>[] interfaces 代理对象类类型
     * InvocationHandler 处理类
     *
     * @param args
     */
    public static void main(String[] args) {
        ProxyOrderService proxyOrderService = new ProxyOrderService(new OrderServiceImpl());
        // 返回代理对象
        OrderService orderService =
                (OrderService) Proxy
                        .newProxyInstance(ProxyOrderService.class.getClassLoader(), new Class[]{OrderService.class}, proxyOrderService);
        orderService.save();
    }

}

执行结果

 代理类源码

生成的代理类源码方法

    /**
     * 生成动态代理源码
     *
     * @param path 保存路径
     * @param var1 代理对象类类型
     */
    private static void saveProxyClass(String path, Class<?>[] var1) {
        byte[] $proxy1s = ProxyGenerator.generateProxyClass("$Proxy1", var1);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(new File(path + "$Proxy1.class"));
            out.write($proxy1s);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

cglib 代理

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

/**
 * 订单接口类
 */
public interface OrderService {
    void save();
}

/**
 * 订单实现类
 */
public class OrderServiceImpl implements OrderService{

    @Override
    public void save() {
        System.out.println("保存订单信息 ...");
    }
}

/**
 * 实现 MethodInterceptor 重写 intercept
 *
 */
public class MyInterceptor implements MethodInterceptor {

    /**
     *
     * @param o 代理对象
     * @param method 被代理对象的方法
     * @param objects 方法入参
     * @param methodProxy 代理方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib代理方法执行之前 ...");
        Object o1 = methodProxy.invokeSuper(o, objects);
        System.out.println("cglib代理方法执行之后 ...");
        return o1;
    }

}

    public static void main(String[] args) {
        // 代理类class文件存入本地磁盘方便我们反编译查看源码
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./code");

        // 通过CGLIB动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        // 设置enhancer对象的父类
        enhancer.setSuperclass(OrderServiceImpl.class);
        // 设置enhancer的回调对象
        enhancer.setCallback(new MyInterceptor());
        // 创建代理对象
        OrderService orderService = (OrderServiceImpl) enhancer.create();
        orderService.save();
    }

运行结果

Java动态代理和cglib比较
生成代理类技术不同
        java动态代理:jdk自带类ProxyGenerator生成class字节码
        cglib:通过ASM框架生成class字节码文件
生成代理类的方式不同
        java动态代理:代理类继承java.lang.reflect.Proxy,实现被代理类的接口
        cglib:代理类继承被代理类,实现net.sf.cglib.proxy.Factory
生成类数量不同
        java动态代理:生成一个proxy类
        cglib:生成一个proxy,两个fastclass类
调用方式不同
        java动态代理:代理类->InvocationHandler->反射调用被代理类方法
        cglib:代理类->MethodInterceptor->调用索引类invoke->直接调用被代理类方法

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值