Java中的动态代理实现代码实例

 更新时间:2023年12月14日 08:39:36   作者:Terisadeng  
这篇文章主要介绍了Java中的动态代理实现代码实例,jdk动态代理本质上是使用被代理对象的类加载器,通过被代理类实现的接口在运行时动态构造出代理类来增强原始类的功能的方法,需要的朋友可以参考下

一、JDK动态代理

jdk动态代理本质上是使用被代理对象的类加载器,通过被代理类实现的接口在运行时动态构造出代理类来增强原始类的功能的方法,需要使用Java的反射机制,通过实现InvocationHandler接口实现JDK动态代理。

1、先定义一个接口

package com.teriste.fanshe;
 
public interface HelloWorld {
    void sayHello(String name);
}

2、定义被代理类

该类实现了接口

package com.teriste.fanshe;
 
public class HelloWorldImpl implements HelloWorld {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello "+name);
    }
}

3、定义代理类

实现InvocationHandler接口

package com.teriste.fanshe;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * JDK动态代理
 * 代理类必须实现了接口
 */
public class JdkProxyHandler 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("在调度真实对象前的服务");
        Object object = method.invoke(target,args);
        System.out.println("在调度真实对象后的服务");
        return object;
    }
    public static void main(String[] args) {
        JdkProxyHandler jdkProxyHandler = new JdkProxyHandler();
        //通过真实对象和代理对象绑定,返回一个代理对象,这个对象和真实对象实现了相同的接口
        HelloWorld helloWorld = (HelloWorld) jdkProxyHandler.bind(new HelloWorldImpl());
        //该接口调用的方法就是代理对象的invoke方法
        helloWorld.sayHello("张三");
    }
}

二、CGLIB动态代理

CGLIB动态代理是通过生成被代理类的子类来增强被代理类功能的方法,因此被代理类必须可以继承。

1、创建被代理类

package com.teriste.fanshe;
import java.lang.reflect.Method;
public class ReflectServiceImpl {
    public void sayHello(String name){
        System.out.println("Hello "+name);
    }
    public static void main(String[] args) {
        ReflectServiceImpl target = null;
        try {
            target = (ReflectServiceImpl)Class.forName("com.teriste.fanshe.ReflectServiceImpl").newInstance();
            Method method = target.getClass().getMethod("sayHello",String.class);
            method.invoke(target,"张三");
        }catch (NoSuchMethodException | ClassNotFoundException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

2、创建代理类

实现MethodInterceptor接口

package com.teriste.fanshe;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
 * cglib动态代理
 * 代理类必须可以继承
 * 无法代理静态方法,需要使用asm修改字节码的静态代理方式
 */
public class CglibProxy implements MethodInterceptor{
    /**
     * 生成CGLIB动态代理对象
     * @param cls 被代理类的CLASS类
     * @return 类的CGLIB代理对象
     */
    public Object getProxy(Class cls){
        //CGLIB enhancer 增强类对象
        Enhancer enhancer = new Enhancer();
        //设置增强类型
        enhancer.setSuperclass(cls);
        //定义代理逻辑对象为当前对象,当前对象必须实现MethodInterceptor.intercept方法
        enhancer.setCallback(this);
        //生成并返回代理对象
        return enhancer.create();
    }
    /**
     * 代理逻辑方法
     * @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("调用真实对象前");
        methodProxy.invokeSuper(o,objects);
        System.out.println("调用真实对象后");
        return null;
    }
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        ReflectServiceImpl reflectService = (ReflectServiceImpl) cglibProxy.getProxy(ReflectServiceImpl.class);
        reflectService.sayHello("张三");
    }
}

三、代理类的静态方法

cglib虽然可以代理类的方法,但是对于类的静态方法却无效,针对静态方法需要使用asm重写类的字节码来实现代理效果。

到此这篇关于Java中的动态代理实现代码实例的文章就介绍到这了,更多相关Java动态代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java.lang.UnsupportedClassVersionError异常正确解决方法

    java.lang.UnsupportedClassVersionError异常正确解决方法

    java.lang.UnsupportedClassVersionError异常通常发生在尝试在较低版本的Java虚拟机上运行使用更高版本的Jav 编译器编译的类文件时,下面就来介绍一下解决方法,感兴趣的可以了解一下
    2024-05-05
  • Java运行时动态生成类实现过程详解

    Java运行时动态生成类实现过程详解

    这篇文章主要介绍了Java运行时动态生成类实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • 解决Java ClassNotFoundException异常的实践步骤

    解决Java ClassNotFoundException异常的实践步骤

    本文详解Java中ClassNotFoundException的常见原因及解决方法,涵盖类路径配置、命名规范、打包问题、依赖管理、ClassLoader使用等,提供排查步骤和工具示例,感兴趣的朋友跟随小编一起学习吧
    2025-08-08
  • Java初学者必会的Map集合及其原理

    Java初学者必会的Map集合及其原理

    这篇文章主要给大家介绍Map集合及其原理,该集合中的信息是key-value形式,Map集合与Collection集合又有什么不同呢,要想搞清楚以上问题,下面跟着小编一起来看看吧
    2023-06-06
  • 浅谈Spring注入模型

    浅谈Spring注入模型

    如果不深入到Spring的源码,是很少有机会了解到Spring的注入模型(AutowireMode)。但是为了扫清我们学习Spring源码的障碍,我们有必要了解下Spring的注入模型,感兴趣的同学可以阅读一下
    2023-04-04
  • 使用JMeter进行接口高并发测试的实现

    使用JMeter进行接口高并发测试的实现

    本文主要介绍了使用JMeter进行接口高并发测试的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • 深入理解Java序列化与反序列化

    深入理解Java序列化与反序列化

    今天教大家深入理解Java的序列化与反序列化,文中介绍的非常详细,有很多代码示例,对正在学习Java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • 详解Java中跳跃表的原理和实现

    详解Java中跳跃表的原理和实现

    跳跃表(Skip list)是有序链表的扩展,简称跳表,它在原有的有序链表上增加了多级索引,通过索引来实现快速查找,实质上是一种可以进行二分查找的有序链表。本文主要为大家介绍了跳跃表的原理和实现,需要的可以参考一下
    2022-12-12
  • 利用java反射机制实现自动调用类的简单方法

    利用java反射机制实现自动调用类的简单方法

    下面小编就为大家带来一篇利用java反射机制实现自动调用类的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • springboot普通类中如何获取session问题

    springboot普通类中如何获取session问题

    这篇文章主要介绍了springboot普通类中如何获取session问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01

最新评论