java中动态代理的实现

发布时间 - 2026-01-10 22:18:18    点击率:

动态代理的实现

使用的模式:代理模式。

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。类似租房的中介。

两种动态代理:

(1)jdk动态代理,jdk动态代理是由Java内部的反射机制来实现的,目标类基于统一的接口(InvocationHandler)

(2)cglib动态代理,cglib动态代理底层则是借助asm来实现的,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。

主要应用的框架:

Spring中的AOP,Struts2中的拦截器

具体实现:

1、定义接口和实现类

package com.example.service;
public interface UserService {
  public String getName(int id);
  public Integer getAge(int id);
}
package com.example.service.impl;
import com.example.service.UserService;
public class UserServiceImpl implements UserService {
  public String getName(int id) {
    System.out.println("------getName------");
    return "cat";
  }
  public Integer getAge(int id) {
    System.out.println("------getAge------");
    return 10;
  }
}

2、jdk动态代理实现

package com.example.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInvocationHandler implements InvocationHandler {
  private Object target;
  /**
   * 绑定委托对象并返回一个代理类
   *
   * @param target
   * @return
   */
  public Object bind(Object target) {
    this.target = target;
    //取得代理对象
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
        target.getClass().getInterfaces(), this);  //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if ("getName".equals(method.getName())) {
      System.out.println("------before " + method.getName() + "------");
      Object result = method.invoke(target, args);
      System.out.println("------after " + method.getName() + "------");
      return result;
    } else {
      Object result = method.invoke(target, args);
      return result;
    }
  }
}
package com.example.jdk;

import com.example.service.UserService;
import com.example.service.impl.UserServiceImpl;

/**
 * 测试类
 */
public class RunJDK {
  public static void main(String[] args) {
    MyInvocationHandler proxy = new MyInvocationHandler();
    UserService userServiceProxy = (UserService) proxy.bind(new UserServiceImpl());
    System.out.println(userServiceProxy.getName(1));
    System.out.println(userServiceProxy.getAge(1));
  }
}

运行结果:

------before getName------
------getName------
------after getName------
cat
------getAge------
10

3、cglib动态代理实现:

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

CGLIB的核心类:

net.sf.cglib.proxy.Enhancer – 主要的增强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用。

net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;

第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用 net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使用,因为它更快。

package com.example.cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLIBProxy implements MethodInterceptor {
  private Object target;
  /**
   * 创建代理对象
   *
   * @param target
   * @return
   */
  public Object getInstance(Object target) {
    this.target = target;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(this.target.getClass());
    // 回调方法
    enhancer.setCallback(this);
    // 创建代理对象
    return enhancer.create();
  }
  @Override
  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
    System.out.println(method.getName());
    Object result = methodProxy.invokeSuper(o, objects);
    System.out.println("++++++after " + methodProxy.getSuperName() + "++++++");
    return result;
  }
}
package com.example.cglib;
import com.example.service.UserService;
import com.example.service.impl.UserServiceImpl;
/**
 * 测试CGLIB
 */
public class RunCGLIB {
  public static void main(String[] args) {
    CGLIBProxy cglibProxy = new CGLIBProxy();
    UserService userService = (UserService) cglibProxy.getInstance(new UserServiceImpl());
    userService.getName(1);
    userService.getAge(1);
  }
}

运行结果:

++++++before CGLIB$getName$0++++++
getName
------getName------
++++++after CGLIB$getName$0++++++
++++++before CGLIB$getAge$1++++++
getAge
------getAge------
++++++after CGLIB$getAge$1++++++

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


# java  # 动态代理  # JDK动态代理  # 代理接口没有实现类  # 实现动态代理方式  # 深入讲解基于JDK的动态代理机制  # JDK动态代理原理:只能代理接口  # 不能代理类问题  # 来实现  # 绑定  # 回调  # 的是  # 这一  # 第一个  # 子类  # 是由  # 则是  # 两种  # 他对  # 它是  # 这是一个  # 更有  # 就不能  # 为其  # 更快  # 因为它  # 第三个  # 第三方 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在IIS中新建站点并配置端口与物理路径?  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  浅谈javascript alert和confirm的美化  如何制作一个表白网站视频,关于勇敢表白的小标题?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  如何在新浪SAE免费搭建个人博客?  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  如何获取免费开源的自助建站系统源码?  EditPlus 正则表达式 实战(3)  在线制作视频网站免费,都有哪些好的动漫网站?  小米17系列还有一款新机?主打6.9英寸大直屏和旗舰级影像  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  JavaScript数据类型有哪些_如何准确判断一个变量的类型  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  edge浏览器无法安装扩展 edge浏览器插件安装失败【解决方法】  php在windows下怎么调试_phpwindows环境调试操作说明【操作】  如何在云指建站中生成FTP站点?  HTML 中如何正确使用模板变量为元素的 name 属性赋值  Laravel观察者模式如何使用_Laravel Model Observer配置  Python结构化数据采集_字段抽取解析【教程】  如何在搬瓦工VPS快速搭建网站?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  在centOS 7安装mysql 5.7的详细教程  iOS UIView常见属性方法小结  作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?  移动端脚本框架Hammer.js  韩国服务器如何优化跨境访问实现高效连接?  大连网站制作公司哪家好一点,大连买房网站哪个好?  如何快速搭建高效简练网站?  如何快速登录WAP自助建站平台?  如何获取PHP WAP自助建站系统源码?  网站建设整体流程解析,建站其实很容易!  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲  如何快速生成高效建站系统源代码?  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  Laravel怎么实现支付功能_Laravel集成支付宝微信支付  如何用IIS7快速搭建并优化网站站点?  Laravel中的Facade(门面)到底是什么原理  javascript中闭包概念与用法深入理解  Laravel怎么在Controller之外的地方验证数据  Android GridView 滑动条设置一直显示状态(推荐)  如何在腾讯云服务器上快速搭建个人网站?  详解阿里云nginx服务器多站点的配置