区分静态代理和动态代理的运行原理

最近在View时,被问到了静态代理和动态代理二者存在什么区别?说实话,当时是回答的时候是有些懵懵的,一时间竟不知从何说起。于是今天特意研究了下,也分享给屏幕前的你,帮你更好的理解下 静态代理与动态代理。

相信每个人都畅享做一个CEO,梦想可以实现财富自由,走向人生巅峰,那么CEO肯定是只处理重要的事情(也就是决策性的实施),接下来我们就以CEO举例,希望可以加深我们的印象。

定义目标类CEO

分为两步:1、定义ICEO接口;2、实现类Ceo实现接口ICEO

  • 定义接口
/**
 * @Description 代理接口
 * @Author Mr.Gao
 * @Date 2024/9/24 23:21
 */
public interface ICEO {

    public void meeting();
}
  • 实现类
/**
 * @Description 实现类
 * @Author Mr.Gao
 * @Date 2024/9/24 23:22
 */
public class Ceo implements ICEO {
    @Override
    public void meeting() {
        System.out.println("老板需要进行开会...");
    }
}

静态代理

通过静态代理方式增强目标类,即就是采用包装类的思想,分为如下几步:1、代理类实现ICEO接口
2、代理类中引入目标类
3、调用目标类的方法,并且在目标类的前后进行增强处理

/**
 * @Description 静态代理
 * @Author Mr.Gao
 * @Date 2024/9/24 23:23
 */
public class CeoStaticProxy implements ICEO {

    private ICEO iceo;

    public CeoStaticProxy(ICEO iceo) {
        this.iceo = iceo;
    }

    @Override
    public void meeting() {
        System.out.println("##增强处理(before),先接待客人,然后通知老板开会!");
        iceo.meeting();
        System.out.println("##增强处理(after),老板开完会了,准备送客~~~");
    }
}
  • 静态代理单元测试类
/**
 * @Description 单元测试静态代理
 * @Author Mr.Gao
 * @Date 2024/9/24 23:27
 */
public class TestStaticProxy {
    public static void main(String[] args) {
        // 创建一个包装类
        CeoStaticProxy staticProxy = new CeoStaticProxy(new Ceo());
        // 开始执行
        staticProxy.meeting();
    }
}
  • 运行结果
    在这里插入图片描述

根据静态代理引出动态代理

经过静态代理可以发现,确实可以达到代理类的效果,但是会引发一个新的问题,那就是需要为每一个目标对象新建一个代理实现类,这样如果少量的话也还可以接受,但是如果量大的话就会特别麻烦,而且显得代码非常的臃肿,为了解决这个问题,则引入了动态代理的概念。

动态代理

JDK动态代理

/**
 * @Description JDK动态代理
 * @Author Mr.Gao
 * @Date 2024/9/24 23:29
 */
public class JdkProxyFactory {
    /**
     * JDK动态代理
     *
     * @param target
     * @return
     */
    public static Object getProxy(Object target) {
        // 保存生成的代理类的字节码文件: jdk8 下的配置,默认生成的路径是项目根目录
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("##增强处理(before),先接待客人,然后通知老板开会!");
                        // 执行目标方法
                        Object invoke = method.invoke(target, args);
                        System.out.println("##增强处理(after),老板开完会了,准备送客~~~");
                        return invoke;
                    }
                }
        );
    }
}

  • JDK动态代理单元测试类
/**
 * @Description 单元测试JDK动态代理
 * @Author Mr.Gao
 * @Date 2024/9/24 23:34
 */
public class TestJdkProxy {
    public static void main(String[] args) {
        // 创建目标类
        Ceo target = new Ceo();
        // 创建目标代理类
        ICEO ceoProxy = (ICEO) JdkProxyFactory.getProxy(target);
        // 执行目标代理类
        ceoProxy.meeting();
    }
}

  • 运行结果
    在这里插入图片描述
  • 生成JDK代理的Class文件

System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”); // 会在当前项目下生成$Proxy0文件
在这里插入图片描述

Cglib动态代理

/**
 * @Description cglib动态代理实现
 * @Author Mr.Gao
 * @Date 2024/9/24 23:45
 */
public class CglibProxyFactory {

    /**
     * 创建cglib动态代理类
     *
     * @param clazz
     * @return
     */
    public static Object getProxy(Class<?> clazz) {
        //指定文件夹生成class文件
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\Project\\xbqx\\multi-thread\\");
        // 创建动态代理增强类
        Enhancer enhancer = new Enhancer();
        // 设置类加载器
        enhancer.setClassLoader(clazz.getClassLoader());
        // 设置被代理类
        enhancer.setSuperclass(clazz);
        // 设置方法拦截器
        enhancer.setCallbacks(new Callback[]{
                new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        System.out.println("##增强处理(before),先接待客人,然后通知老板开会!");
                        // 执行目标方法
                        Object invokeSuper = methodProxy.invokeSuper(o, objects);
                        System.out.println("##增强处理(after),老板开完会了,准备送客~~~");
                        return invokeSuper;
                    }
                },
                new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        Object invokeSuper = methodProxy.invokeSuper(o, objects);
                        return invokeSuper;
                    }
                }
        });
        // 对不同方法设置不同的回调逻辑,CallbackFilter中return值为回调数组Callback[]的下标
        enhancer.setCallbackFilter(new CallbackFilter() {
            @Override
            public int accept(Method method) {
                //System.out.println("执行方法名称:" + method.getName());
                if (method.getName().equals("meeting")) {
                    return 0;
                } else {
                    return 1;
                }
            }
        });
        // 创建代理类
        return enhancer.create();
    }

}
  • Cglib动态代理单元测试类
/**
 * @Description cglib动态代理
 * @Author Mr.Gao
 * @Date 2024/9/24 23:54
 */
public class TestCglibProxy {
    public static void main(String[] args) {
        // 创建Cglib代理
        ICEO ceoProxy = (ICEO) CglibProxyFactory.getProxy(Ceo.class);
        // 执行代理方法
        ceoProxy.meeting();
    }
}
  • 运行结果
    在这里插入图片描述
  • 生成Cglib的Class类
    在这里插入图片描述

JDK动态代理和Cglib动态代理区别

1、JDK动态代理是implements目标类的接口; 而Cglib动态代理是继承目标,作为目标类的子类。
2、JDK动态代理的目标类必须实现接口;而Cglib动态代理的目标类不能被final修饰。

综上所述,是我结合代码层面对静态代理和动态代理的理解,也希望可以帮助到您,加深理解,若存在书写错误的地方,望指正。
今日推荐一言:在日出之际,让我们对世界说早安!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值