java的动态代理

1. 什么是动态代理

代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色。Java的动态代理比代理的思想更前进了一步,它可以动态地创建并代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的策略。

大道理上讲代理是一种软件设计模式,目的地希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过直接与明星对话的情况下,而通过明星经纪人(代理)与其产生间接对话。

2. 代理的使用场景

(1)设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑(sometimes the code is really like shit),这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强。

(2)我们在使用RPC框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 。那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻辑,某种程度上也是客户端代码和框架松耦合的一种表现。

(3)Spring的AOP机制就是采用动态代理的机制来实现切面编程。Spring Aop学习总结 

3. 代理分类

  • 静态代理:静态代理是在编译时就将接口、实现类、代理类一股脑儿全部手动完成
  • 动态代理:在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能

4. 静态代理使用举例

我们先创建一个接口,java api代理机制求被代理类必须要实现某个接口,对于静态代理方式代理类也要实现和被代理类相同的接口。

1public interface Person { 2 public void sayHello(String name); 3 public void interduce(String name, int age); 4} 5 6public class Student implements Person{ 7 @Override 8 public void sayHello(String name) { 9 System.out.println("Student sayHello start"); 10 System.out.println("Hello " + name); 11 System.out.println("Student sayHello end"); 12 } 13 14 @Override 15 public void interduce(String name, int age){ 16 System.out.println("Student interduce start"); 17 System.out.println("My name is " + name + ". I'm " + age + " years old"); 18 System.out.println("Student interduce end"); 19 } 20} 21 22import java.lang.reflect.Proxy; 23 24public class StaticProxyTest implements Person{ 25 private Person person; 26 27 public StaticProxyTest(Person person){ 28 this.person = person; 29 } 30 31 @Override 32 public void sayHello(String name){ 33 System.out.println("Static Proxy Test sayHello begin"); 34 person.sayHello(name); 35 System.out.println("Static Proxy Test sayHello end"); 36 } 37 38 @Override 39 public void interduce(String name, int age){ 40 System.out.println("Static Proxy Test interduce start"); 41 person.interduce(name, age); 42 System.out.println("Static Proxy Test interduce end"); 43 } 44 45 public static void main(String[] args){ 46 Student student = new Student(); 47 StaticProxyTest staticProxyTest = new StaticProxyTest(student); 48 staticProxyTest.sayHello("static proxy test"); 49 staticProxyTest.interduce("static proxy test", 1); 50 } 51}

5. 动态代理

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface),另一个则是 Proxy(Class)。这一个类和接口是实现我们动态代理所必须用到的。

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法: 

1Object invoke(Object proxy, Method method, Object[] args) throws Throwable 2 3proxy:  指代我们所代理的那个真实对象 4method:  指代的是我们所要调用真实对象的某个方法的Method对象 5args:  指代的是调用真实对象某个方法时接受的参数

接下来我们来看看Proxy这个类,Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:

1public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 2 3loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 4interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 5h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

动态代理举例:

1import java.lang.reflect.InvocationHandler; 2import java.lang.reflect.Method; 3import java.lang.reflect.Proxy; 4 5public class MyInvocationHandler implements InvocationHandler { 6 public Object object; 7 8 public MyInvocationHandler(Object object){ 9 this.object = object; 10 } 11 12 @Override 13 public Object invoke(Object proxy, Method method, Object[] args) 14 throws Throwable{ 15 System.out.println("MyInvocationHandle proxy begins"); 16 System.out.println("proxy: " + proxy.getClass().getName()); 17 System.out.println("method: " + method.getName()); 18 19 for(Object o : args) System.out.println("arg: " + o); 20 21 method.invoke(object, args); 22 System.out.println("MyInvocationHandle proxy ends"); 23 return null; 24 } 25 26 public static void main(String[] args){ 27 Student student = new Student(); 28 MyInvocationHandler myInvocationHandler = new MyInvocationHandler(student); 29 Person proxyPerson = (Person) Proxy.newProxyInstance(student.getClass().getClassLoader(), student.getClass().getInterfaces(), 30 myInvocationHandler); 31 32 proxyPerson.sayHello("proxyPersonSayHello"); 33 proxyPerson.interduce("proxyPersonInterduce", 1); 34 } 35}

参考文档:

详解java动态代理机制以及使用场景:https://blog.csdn.net/u011784767/article/details/78281384 

java动态代理作用及源码分析:https://www.jianshu.com/p/9d5ef621f2d1

java动态代理机制详解:https://www.cnblogs.com/xiaoluo501395377/p/3383130.html

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java中的反射和代理

  Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制。java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性。这些都是java的基础知识,要想成为一名合格的程序猿,必须掌握!Java反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知

java技术学习路线(自用)

一:常见模式与工具    1.常用设计模式:                 1.1.Proxy代理模式:指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。详见https://www.cnblogs.com/qifengshi/p/6566752.html       

RPC框架手撕之路---java反射以及动态代理机制

在上一篇文章中,我们提到了,RPC框架所需要的java基础,第一点就是java的动态代理机制,动态代理机制的基础是反射,无论是在实际编程或者是面试时,都是java知识的重中之重。java反射:定义:在运行状态中,对于任意一个类,都能够知道这一个类的所有属性和方法,对于任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息以及动态调用类方法

CGLIB介绍与原理(通过继承的动态代理)

一、什么是CGLIB?CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。二、CGLIB原理CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的

Spring的两种代理JDK和CGLIB的区别浅谈

一、原理区别:java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以