Java基础 代理模式:静态、动态、cglib;及 spring 中 动态、cglib 两种方式的示例

Java基础 代理模式:静态、动态、cglib;及 spring 中 动态、cglib 两种方式的示例

一、代理模式介绍

代理模式,也称委托模式,是结构型设计模式之一;
代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改代理目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

1.1、静态代理与动态代理的区别主要在:
  • 静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
  • 动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中

特点:动态代理中,代理对象不需要实现接口,但是要求被代理目标对象必须实现接口,否则不能使用动态代理。

二、Java 代理模式

java 中常用的代理模式有3种:静态代理、动态代理、cglib 动态代理

2.1、静态代理模式

使用静态代理的基本步骤:

  1. 定义公共接口;
  2. 被代理目标对象实现公共接口中的方法;
  3. 代理对象实现公共接口中的方法,通过方法调用被代理目标对象的实现方法。

缺点:

  • 冗余。由于代理对象要实现与被代理目标对象一致的接口,会产生过多的代理类。
  • 不易维护。一旦接口增加方法,被代理目标对象与代理对象都要进行修改。很难维护这么多代理类和被代理类之间的关系。

示例:
无,太简单,不想写;

2.2、动态代理模式

使用动态代理的基本步骤:

  1. 定义公共接口;
  2. 被代理目标对象实现公共接口中的方法;
  3. 定义一个实现 InvocationHandler 的代理工厂类。
  4. 通过代理工厂类的对象,创建代理对象;
  5. 代理对象调用被代理目标对象方法;

示例:

  1. 定义公共接口
package com.zk.demo.proxy;

/**
 * @ClassName: ZKDoSomethingInterface
 * @Description: TODO(simple description this class what to do. )
 * @author Vinson
 * @version 1.0
 */
public interface ZKDoSomethingInterface {

    /**
     * 做点啥
     *
     * @Title: doSomething
     * @Description: TODO(simple description this method what to do.)
     * @author Vinson
     * @date Aug 3, 2024 8:36:04 AM
     * @param param
     * @return
     * @return int
     */
    int doSomething(int param);

}
  1. 被代理目标对象实现公共接口中的方法;
package com.zk.demo.proxy;
/** 
* @ClassName: ZKDoSomethingImpl 
* @Description: TODO(simple description this class what to do. ) 
* @author Vinson 
* @version 1.0 
*/
public class ZKDoSomethingImpl implements ZKDoSomethingInterface { // 有实现接口

    private int mP;

    public ZKDoSomethingImpl(int mP) {
        this.mP = mP;
    }

    @Override
    public int doSomething(int param) {
        System.out
                .println("[^_^:20240803-0838-001] ZKDoSomethingImpl.DoSomething 给参数 param:" + param + " 增加:" + this.mP);
        param = this.mP + param;
        return param;
    }

}
  1. 定义一个实现 InvocationHandler 处理类及工厂类。
package com.zk.demo.proxy.dynamicProxy;

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

/** 
* @ClassName: ZKInvocationHandler 
* @Description: TODO(simple description this class what to do. ) 
* @author Vinson 
* @version 1.0 
*/
public class ZKInvocationHandler implements InvocationHandler {

    /**
     * 被代理的真实对象;
     * 
     * 必须实现一个或多个接口
     */
    private Object target;

    public ZKInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("[^_^:20240803-0855-001] ZKInvocationHandler proxy:" + proxy.getClass());
        System.out.println("[^_^:20240803-0855-001] ZKInvocationHandler method:" + method.getName());
        Object rev = method.invoke(this.target, args);
        System.out.println("[^_^:20240803-0855-001] ZKInvocationHandler 执行被代理目标对象的方法结束:" + rev);
        return rev;
    }

}
package com.zk.demo.proxy.dynamicProxy;

import java.lang.reflect.Proxy;

/** 
* @ClassName: ZKDynamicProxyFactory 
* @Description: TODO(simple description this class what to do. ) 
* @author Vinson 
* @version 1.0 
*/
public class ZKDynamicProxyFactory {

    @SuppressWarnings("unchecked")
    public <T> T getProxyInstance(Object target) {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new ZKInvocationHandler(target));
    }

}
  1. 测试
package com.zk.demo.proxy.dynamicProxy;

import org.junit.Test;
import com.zk.demo.proxy.ZKDoSomethingImpl;
import com.zk.demo.proxy.ZKDoSomethingInterface;
import junit.framework.TestCase;

/** 
* @ClassName: ZKDynamicProxyFactoryTest 
* @Description: TODO(simple description this class what to do. ) 
* @author Vinson 
* @version 1.0 
*/
public class ZKDynamicProxyFactoryTest {

    @Test
    public void test() {
        try {
            ZKDoSomethingImpl dsImpl = new ZKDoSomethingImpl(3);
            ZKDoSomethingInterface dsProxy = null;
            int result = 0;

            ZKDynamicProxyFactory dpf = new ZKDynamicProxyFactory();
            dsProxy = dpf.getPr
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

征客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值