首页 > 编程语言 >Java动态代理

Java动态代理

时间:2024-11-25 10:33:18浏览次数:10  
标签:Java target Object 代理 proxy 动态 public

理解

Java 中的动态代理是一种在运行时创建代理对象的机制。动态代理允许程序在运行时决定代理对象的行为,而不需要在编译时确定。它通过代理模式为对象提供了一种机制,使得可以在不修改目标对象的情况下对其行为进行增强或调整。

代理可以看作是调用目标的一个包装,通常用来在调用真实的目标之前进行一些逻辑处理,消除一些重复的代码.。

静态代理指的是我们预先编码好一个代理类,而动态代理指的是运行时生成代理类。

扩展知识

动态代理主要用途

  • - 简化代码:通过代理模式,可以减少重复代码,尤其是在横切关注点(如日志记录、事务管理、权限控制等)方面。

  • - 增强灵活性:动态代理使得代码更具灵活性和可扩展性,因为代理对象是在运行时生成的,可以动态地改变行为。

  • - 实现 AOP:动态代理是实现面向切面编程(AOP,Aspect-Oriented Programming)的基础,可以在方法调用前后插入额外的逻辑。

  • ## Java 动态代理与 CGLIB 代理:

  • - Java 动态代理:只能对接口进行代理,不支持对类进行代理。

  • - CGLIB 代理:通过字节码技术动态生成目标类的子类来实现代理,支持对类(非接口)进行代理。

JDK 示例代码:

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


// 目标接口
interface MyService {
   void doSomething();
}


// 目标对象的实现
class MyServiceImpl implements MyService {
   @Override
   public void doSomething() {
       System.out.println("Doing something...");
   }
}


// 动态代理处理器
class MyInvocationHandler implements InvocationHandler {
   private final Object target;


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


   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       System.out.println("Before method call");
       Object result = method.invoke(target, args);
       System.out.println("After method call");
       return result;
   }
}

// 使用动态代理public class Main {   public static void main(String[] args) {       MyService target = new MyServiceImpl();       MyService proxy = (MyService) Proxy.newProxyInstance(           target.getClass().getClassLoader(),           target.getClass().getInterfaces(),           new MyInvocationHandler(target)       );       proxy.doSomething();   }}

CGLIB代码:​​​​​​​

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


// 目标类
class MyService {
   public void doSomething() {
       System.out.println("Doing something...");
   }
}


// CGLIB 代理处理器
class MyInterceptor implements MethodInterceptor {
   @Override
   public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
       System.out.println("Before method call");
       Object result = proxy.invokeSuper(obj, args);
       System.out.println("After method call");
       return result;
   }
}


// 使用 CGLIB 动态代理
public class Main {
   public static void main(String[] args) {
       Enhancer enhancer = new Enhancer();
       enhancer.setSuperclass(MyService.class);
       enhancer.setCallback(new MyInterceptor());


       MyService proxy = (MyService) enhancer.create();
       proxy.doSomething();
   }
}

两种代理的区别:

**JDK动态代理**是基于接口的,所以要求代理类一定是有定义接口的。

**CGLIB**基于 ASM 字节码生成工具,它是通过继承的方式生成目标类的子类来实现代理类,所以要注意 final 方法它们之间的性能随着 JDK 版本的不同而不同。

jdk6 下,在运行次数较少的情况下,jdk动态代理与 caglib 差距不明显,甚至更快一些。而当调用次数增加之后,cglib表现稍微更快一些。

jdk7 下,情况发生了逆转!在运行次数较少(1,000,000)的情况下,jdk动态代理比 cglib 快了差不多

30%;而当调用次数增加之后(50,000,000),动态代理比 cqlib 快了接近1倍。

jdk8 表现和 jdk7 基本一致。

形象理解(打官司)

1、主人公张三首先得明确张三要干嘛:对,他要打官司,去告李四,好,新建接口去告李四​​​​​​​

//定义打官司接口
interface Service{
    void gan();
}


//定义需要被代理实现的类
class ServiceImpl implements Service{
    @Override
    public void gan() {
        System.out.println("我要告李四!");
    }
}

2、接下来去找律师,java动态代理呢你就只能找法院安排好的律师和他们商量怎么干

​​​​​​​

public class ServiceInvocationHandle implements InvocationHandler {
//定义给律师的目标,你得给律师具体安排的活,干李四
    private final Object target;


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


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //准备好文件,目标是干李四,args怎么干
        Object result = method.invoke(target,args);
        System.out.println("开干,奥里给!");
        return result;
    }
}

3、到法院找到律师,找律师前得注意你要干李四因为啥,才好找啥样的律师而不是一股脑都去找仲裁

​​​​​​​

 public static void main(String[] args) {
//把昨晚起草好的文件带上
        Service target = new ServiceImpl();


        Service proxy = (Service) Proxy.newProxyInstance(
//法院根据你得文件给你定位问题
             target.getClass().getClassLoader(),
//法院根据你得问题给你分类(仲裁、离婚、分财产)
             target.getClass().getInterfaces(),
//法院根据你得问题类别给你找相应的律师
             new ServiceInvocationHandle(target)
        );


//律师猛干,拿下李四
        proxy.gan();
    }

图片

总结:

**通过InvocationHandler 得到切面;再通过Proxy根据目标类、接口、切面类得到相应的代理类;最后通过切面类的invoke方法,根据反射获取目标类的属性方法去操作。**

CGLIB理解相似但是技术不同java动态通过反射,CGLIB通过字节码。所以CGLIB是通过继承,不需要接口来操作,操作大同小异

import net.sf.cglib.proxy.Enhancer;


public class CglibDynamicProxyDemo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Service.class);
        enhancer.setCallback(new ServiceMethodInterceptor());


        Service proxy = (Service) enhancer.create();
        proxy.perform();
    }
}

标签:Java,target,Object,代理,proxy,动态,public
From: https://blog.csdn.net/cgk_ALEM/article/details/144020695

相关文章

  • 什么情况发生栈溢出?思维导图 代码示例(java 架构)
    栈溢出(StackOverflow)的认识定义栈溢出是指程序在执行过程中,由于栈空间不足而引发的一种错误。栈是用于存储方法调用时的局部变量和方法调用信息的数据结构。当栈的空间被耗尽时,JVM将抛出StackOverflowError。常见原因递归调用过深:递归函数没有正确的终止条件,导致......
  • JavaScript有几种类型值?能否画出它们的内存图?
    JavaScript有七种原始数据类型和一种引用类型:原始数据类型(PrimitiveDataTypes):存储在栈(Stack)内存中,值直接存储在变量访问的位置。Boolean:true或falseNull:只有一个值null,表示空或不存在的值。Undefined:变量声明了但未赋值时的默认值undefined。Number:所......
  • [Java]微服务配置管理
    介绍代码拆分为微服务后,每个服务都有自己的配置文件,而这些配置文件中有很多重复的配置,并且配置变化后需要重启服务,才能生效,这样就会影响开发体验和效率配置管理服务可以帮助我们集中管理公共的配置,并且nacos就可以实现配置管理服务配置共享我们可以把微服......
  • 深入解析 Java LinkedList:从基本特点到常用方法的全面介绍
    LinkedList是Java集合框架中非常常用的一种实现类,主要用于存储有序元素的链式结构。与ArrayList这种基于数组的实现不同,LinkedList使用双向链表来管理数据。在本文中,我们将从LinkedList的基本特点、继承关系、扩容机制、常用方法源码介绍、增删改查等多个方面详细解读......
  • Java项目实战II基于SPringBoot的玩具销售商城管理系统(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、核心代码五、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言随着儿童娱乐与教育需求的日益增长,玩具市场呈现出蓬勃......
  • 解决国外代理IP频繁掉线的技巧
    在互联网和经济全球化迅猛发展的今天,国外IP代理服务已成为国内用户关注的焦点。然而,许多用户在使用国外代理IP时常常遭遇到频繁掉线的问题。在本文中,我们将分享一些解决这一问题的方法,确保您能够更加顺畅地使用国外代理IP服务。解决方法一:检查网络连接要确保国外代理IP服务......
  • 自建动态IP代理为何无法使用及解决方法
    在网络使用中,有时候我们会尝试自建动态IP来实现一些特定的需求,例如访问受限内容或保护隐私。然而,有时我们会遇到无法使用的情况。本文将探讨无法使用的可能原因,并提供相应的解决方法。1. 可能原因a.网络配置问题自建动态IP通常需要正确的网络配置才能运行。如果网络配置......
  • C++20中的Concepts 与 Java/C#中的范型约束
    C++20中的Concepts与Java/C#中的范型约束大家好!最近对C++20中的Concepts非常上头,上一篇聊了C++20中的Concepts与TypeScript,那么今天,就索性连Java和C#中的相似特性一起聊了算了。C++20引入了概念(Concepts),它是一种用来对模板参数进行约束的机制,能够提升模板编程的类型安......
  • Java基于微信小程序的校园跑腿平台(V2.0)
    博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w+、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌......
  • 【分享】这篇教程助力你成为 JavaScript 糕手!(十一)
    第十一章:异步编程11.1异步编程的概念在JavaScript中,异步编程是一种非常重要的编程模式,它用于处理那些不会立即完成的操作,而是在一段时间后才会返回结果的任务。传统的同步编程模式下,代码是按照从上到下的顺序依次执行的,每一行代码都必须等待前一行代码执行完毕后才会......