美文网首页
动态代理

动态代理

作者: 香瓜会飞 | 来源:发表于2020-09-23 12:22 被阅读0次

代理模式

静态代理:

静态得代理模式和装饰器模式十分相像,语法也是差不多,但是他们俩个逻辑思想上不太相同得,代理模式是代理对象来代理被代理对象并可以对代理对象进行一系列的增强(enhance)操作。装饰器模式的主要思想是,为一个主体类加上需要装饰的内容,而且装饰器中进行嵌套的时候传入的是java类。而代理模式传入的是接口。下面是基本的静态代理UML图


2050.png
public class Tank implements Movable{

 public static void main(String[] args){
 TimeProxy tp = new TimeProxy(new Tank);
 TankLogProxy tlp = new TankLogProxy(tp);
 tp.move();
 tlp.move();
 }
​
 /**
 * 模拟坦克移动了一段儿时间
 */
 @Override
 public void move() {
 System.out.println("Tank moving claclacla...");
 try {
 Thread.sleep(new Random().nextInt(10000));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
}
​
​
class TimeProxy implements Movable{
 Movable m;
 public  TimeProxy( Movable m){
 this.m = m;
 }
 public void move (){
 System.out.println("start moving...");
 m.move();
 long end = System.currentTimeMillis();
 System.out.println("stopped!");
 }
​
} 
class TankLogProxy implements Movable {
 Movable m;
 public TankLogProxy(Movable m) {
 this.m = m;
 }
 @Override
 public void move() {
 System.out.println("start moving...");
 m.move();
 long end = System.currentTimeMillis();
 System.out.println("stopped!");
 }
}
​
interface Movable{
 void move();
}

JDK动态代理

JDK动态代理是Jdk默认带的代理模式,因为静态代理模式的代码,他只能固定实现某一接口代理,或者是直接将代理对象设置为Object类型的对象,这样的话,在进行获取对象的时候需要进行类型的强制转换。十分不方便。为了解决这种问题,就产生了动态代理,JDK默认的动态代理必须要有接口,没有接口的话不能进行实现。

//Proxy对象中的 ProxyGenerator.generateProxyClass()方法是生成指定的代理类方法,他的底层是通过ASM来进行操作二进制码来生成代理对象的。生成的代理对象是看不见的。如果想要在自己的项目中看见代理对象的话。需要设置:ProxyGenerator中的saveGeneratedFiles属性值,该属性值为true的时候就会生成代理对象,生成的代理对象是class字节码文件,使用IDEA反编译之后我们可以看见里面有生成的代理方法,里面做了一些前置和后置的处理。并且还会增加toString() hashCode() 等方法。(生成的代理对象在最下方)

public class Tank implements Movable{
​
 public static void main(String[] args){
 Movable m = (Movable)Proxy.newProxyInstance(Tank.class.getClassLoader(), new Class[]{Movable.class}, 
 new InvocationHandler() {
 @Override
 public Object invoke(Object proxy,  Method method,  Object[] args) throws Throwable {
 System.out.println("method start..");
 Object o = method.invoke(this,args)
 System.out.println("method end..");
 return o;
 }
 });
 }
​
 /**
 * 模拟坦克移动了一段儿时间
 */
 @Override
 public void move() {
 System.out.println("Tank moving claclacla...");
 try {
 Thread.sleep(new Random().nextInt(10000));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
}
​
interface Movable{
 void move();
}

CGlib动态代理

因为JDK默认的动态代理模式,必须要有接口才能够实现,加入没有接口的话就不能够实现了么,为了解决这个问题就有了CGlib动态代理。CGlib动态代理可以在没有接口的情况下就能生成代理对象。但是final不能进行代理。因为CGlib和JDK动态代理一样,也是实现了ASM,也是通过直接修改二进制文件来生成class文件。如果通过ASM修改final代理类,将final去掉的话也是可以进行代理的。Spring使用的动态代理就是CGlib。

具体代码如下:

public class Main{
​
 public static void main(String[] args){
 Enhancer enhancer = new Enhancer();
 enhancer.setSuperclass(Tank.class);

 //第一种形式
 enhancer.setCallback(new MethodInterceptor() {
 @Override
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
 System.out.println(o.getClass().getSuperclass().getName());
 System.out.println("before");
 Object result = null;
 result = methodProxy.invokeSuper(o, objects);
 System.out.println("after");
 return result;
 });

 //第二种形式
 enhancer.setCallback(new TimeMethodInterceptor());
 Tank tank = (Tank)enhancer.create();
 tank.move();
 }
​
​
}

class TimeMethodInterceptor implements MethodInterceptor {
​
 @Override
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
​
 System.out.println(o.getClass().getSuperclass().getName());
 System.out.println("before");
 Object result = null;
 result = methodProxy.invokeSuper(o, objects);
 System.out.println("after");
 return result;
 }
}
​
class Tank {
 public void move() {
 System.out.println("Tank moving claclacla...");
 try {
 Thread.sleep(new Random().nextInt(10000));
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
}

生成的代理对象 Proxy0

package com.mashibing.dp.proxy.v10;
​
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
​
final class $Proxy0 extends Proxy implements Movable {
 private static Method m1;
 private static Method m3;
 private static Method m2;
 private static Method m0;
​
 public $Proxy0(InvocationHandler var1) throws  {
 super(var1);
 }
​
 public final boolean equals(Object var1) throws  {
 try {
 return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
 } catch (RuntimeException | Error var3) {
 throw var3;
 } catch (Throwable var4) {
 throw new UndeclaredThrowableException(var4);
 }
 }
​
 public final void move() throws  {
 try {
 super.h.invoke(this, m3, (Object[])null);
 } catch (RuntimeException | Error var2) {
 throw var2;
 } catch (Throwable var3) {
 throw new UndeclaredThrowableException(var3);
 }
 }
​
 public final String toString() throws  {
 try {
 return (String)super.h.invoke(this, m2, (Object[])null);
 } catch (RuntimeException | Error var2) {
 throw var2;
 } catch (Throwable var3) {
 throw new UndeclaredThrowableException(var3);
 }
 }
​
 public final int hashCode() throws  {
 try {
 return (Integer)super.h.invoke(this, m0, (Object[])null);
 } catch (RuntimeException | Error var2) {
 throw var2;
 } catch (Throwable var3) {
 throw new UndeclaredThrowableException(var3);
 }
 }
​
 static {
 try {
 m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
 m3 = Class.forName("com.mashibing.dp.proxy.v10.Movable").getMethod("move");
 m2 = Class.forName("java.lang.Object").getMethod("toString");
 m0 = Class.forName("java.lang.Object").getMethod("hashCode");
 } catch (NoSuchMethodException var2) {
 throw new NoSuchMethodError(var2.getMessage());
 } catch (ClassNotFoundException var3) {
 throw new NoClassDefFoundError(var3.getMessage());
 }
 }
}

相关文章

  • 面试系列~动态代理实现与原理

    动态代理有JDK动态代理, CGLIB动态代理, SpringAOP动态代理 一,JDK动态代理  jdk动态代理...

  • 编程常用的设计模式

    动态代理和静态代理 静态代理 动态代理 静态代理与动态代理的区别 JDK中的动态代理和CGLIB 实现动态代理的方...

  • Spring的AOP原理分析

    一 动态代理 动态代理分为JDK动态代理和CGLIB动态代理 jdk动态代理 被代理类(目标类)和代理类必须实现同...

  • 设计模式之代理模式

    代理分为静态代理和动态代理。 动态代理又包括基于JDK的动态代理、基于CGlib 的动态代理、基于Aspectj实...

  • Java高级主题(五)——动态代理

    代理可以分为静态代理、动态代理,动态代理又可以分为 jvm的动态代理 和 cglib的动态代理。像spring框架...

  • 动态代理

    动态代理分为两类:1、基于接口的动态代理; (JDK动态代理 )2、基于类的动态代理;(cglib动态代理)3、J...

  • 动态代理的两种方式

    静态代理就不说了,基本用到的都是动态代理。 Java中动态代理有JDK动态代理和CGLIB动态代理。 JDK代理的...

  • Java动态代理

    通过以下几种方式介绍动态代理 动态代理涉及到的类 动态代理用法 Proxy类解析 动态代理类解析 动态代理涉及到的...

  • Spring之代理模式

    九、代理模式 目录:静态代理、动态代理AOP的底层机制就是动态代理。代理模式分为静态代理和动态代理。接触aop之前...

  • Java 代理

    静态代理 动态代理 动态代理, 日志切片使用反射获得方法 动态代理, 自定义注解(对注解的方法,使用动态代理添加切...

网友评论

      本文标题:动态代理

      本文链接:https://www.haomeiwen.com/subject/tfdzyktx.html