首页 > 编程语言 > 详细

JAVA中的代理,静态代理和动态代理,cglib

时间:2020-01-12 17:05:19      阅读:108      评论:0      收藏:0      [点我收藏+]

1.什么是代理?

1.1 概述

代理:从文字意思解读,也就是说代替某个人完成某件事,代替打理

【示例】

你现在遇到一场官司,但是你解决不了,你需要一名律师,律师代替你去打这场官司。

你现在生病了,需要看病,但是你自己没法给自己看病,因此你需要医生,医生替你看病。

假设你是一个歌星,很红,你只会唱歌,对接单子这种事非常不感冒,因此你需要一个经济人,经纪人负责接活谈钱,时间安排,你只需要负责唱歌就行了。这就是代理。

2.什么是静态代理?

示例

还是以歌星为例:

TargetClass是一个歌手,他只会唱歌,但是他需要钱来养活自己才可以去唱歌,不巧的是他对接单子这种事非常不感冒,因此他请了一个经纪人

 package com.sxt.target;
 ?
 /**
  * 被代理的类
  */
 public class TargetClass {
     public void sing(){
         System.out.println("歌手:去唱歌");
    }
 }

经纪人:ProxyClass 负责安排时间,接活

 package com.sxt.target;
 ?
 /**
  * 代理类
  */
 public class ProxyClass {
 ?
     // 代理的类对象
     TargetClass targetClass;
 ?
     public ProxyClass(TargetClass targetClass) {
         this.targetClass = targetClass;
    }
 ?
     public void sing(){
         System.out.println("经纪人:确定时间");
         System.out.println("经纪人:下周日");
         targetClass.sing();
    }
 }
 ?

测试

 package com.sxt.target;
 ?
 public class Test {
     public static void main(String[] args) {
         // 被代理的类对象
         TargetClass targetClass = new TargetClass();
         // 代理类对象
         ProxyClass proxyClass = new ProxyClass(targetClass);
         proxyClass.sing();
    }
 }

输出结果:

 经纪人:确定时间
 经纪人:下周日
 歌手:去唱歌

3.什么是动态代理?

动态的为需要代理的类,创建了一个代理类,.不再需要开发者定义具体的代理的类.这种方式,就是动态代理.JDK为此制定了一个标准.

proxy:是所有代理类的基类,父类

proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类.

 public static Object newProxyInstance(ClassLoader loader,//类加载器 当前类的加载器
                                       Class<?>[] interfaces,//interfaces 接口的Class对象
                                       InvocationHandler handler) // hanlder 代理类的处理器
                                throws IllegalArgumentException

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

接口:InvocationHandler 与代理类关联调用程序的处理器

创建config类

 package com.sxt.target;
 ?
 public class config {
     // 开启事务方法的前缀
     public static String[] preFix = {"add","update","delete"};
 }
 ?

创建TargetClassInteterface接口

 package com.sxt.target;
 ?
 /**
  * 被代理类的接口
  */
 public interface TargetClassInteterface {
     public void addUser();
     public void deleteUser();
     public void updateUser();
     public void selectUser();
 }
 ?

创建TargetClass

 package com.sxt.target;
 ?
 /**
  * 具体的代理类
  */
 public class TargetClass implements TargetClassInteterface {
     @Override
     public void addUser() {
         System.out.println("添加方法");
    }
 ?
     @Override
     public void deleteUser() {
         System.out.println("删除方法");
    }
 ?
     @Override
     public void updateUser() {
         System.out.println("修改方法");
    }
 ?
     @Override
     public void selectUser() {
         System.out.println("查询方法");
    }
 }

创建TransctionManager

 package com.sxt.target;
 ?
 /**
  * 事务管理器,具体的增强
  */
 public class TransctionManager {
 ?
     public void beginTrancation(){
         System.out.println("开启事务");
    }
 ?
     public void commitTrancation(){
         System.out.println("提交事务");
    }
 ?
 }
 ?

创建ProxyHanlder

 package com.sxt.target;
 ?
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 ?
 public class ProxyHanlder implements InvocationHandler {
 ?
     // 被代理的目标 此时类型时 Object 那么传入任何类型都可以
     private Object proxyTarget;
 ?
     public ProxyHanlder(Object proxyTarget) {
         this.proxyTarget = proxyTarget;
    }
 ?
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         String methodName = method.getName();
         for (String name : config.preFix) {
             if(methodName.startsWith(name)){
                 new TransctionManager().beginTrancation();
            }
        }
         Object obj = method.invoke(proxyTarget, args);
         for (String name : config.preFix) {
             if(methodName.startsWith(name)){
                 new TransctionManager().commitTrancation();
            }
        }
         return obj;
    }
 }
 ?

创建测试类

 package com.sxt.target;
 ?
 import java.lang.reflect.Proxy;
 ?
 public class Test {
 ?
     public static void main(String[] args) {
         // 创建了被代理的目标
         TargetClassInteterface targetInterface = new TargetClass();
         //创建代理类的处理器
         ProxyHanlder handler = new ProxyHanlder(targetInterface);
         //创建代理类
         TargetClassInteterface proxyObj = (TargetClassInteterface) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[] {TargetClassInteterface.class}, handler);
         proxyObj.addUser();
         System.out.println("======================");
         proxyObj.deleteUser();
         System.out.println("======================");
         proxyObj.updateUser();
         System.out.println("======================");
         proxyObj.selectUser();
         System.out.println("======================");
    }
 ?
 }
 ?

输出结果:

 开启事务
 添加方法
 提交事务
 ======================
 开启事务
 删除方法
 提交事务
 ======================
 开启事务
 修改方法
 提交事务
 ======================
 查询方法
 ======================

3.1 动态代理源码分析

编辑Test

 package com.sxt.target.target;
 ?
 import java.lang.reflect.Proxy;
 ?
 public class Test {
 ?
     public static void main(String[] args) {
 ?
         // 保存生成的文件
      System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
 ?
 ?
         // 创建了被代理的目标
         TargetClassInteterface targetInterface = new TargetClass();
         //创建代理类的处理器
         ProxyHanlder handler = new ProxyHanlder(targetInterface);
         //创建代理类
         TargetClassInteterface proxyObj = (TargetClassInteterface) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[] {TargetClassInteterface.class}, handler);
         proxyObj.addUser();
         System.out.println("======================");
 ?
    }
 ?
 }
 ?

System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");然后打开你的本地文件位置,找到D:\workspace2019_12_10\ide-code\java-spring-proxy\com\sun\proxy下的$Proxy0.class文件,再经过反编译工具编译,最后变成下面这段代码啦。

源码分析代码

 package com.sun.proxy;
 ?
 import com.sxt.target2.TargetClassInteterface;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.UndeclaredThrowableException;
 // 生成的代理类 $Proxy0   是 Proxy 子类   且是 TargetClassInteterface 实现类  
 // 那么这个代理类 就要有 TargetClassInteterface 里面抽象方法
 public final class $Proxy0   extends Proxy     implements TargetClassInteterface   {
 
  private static Method m0;   //============> Object类中的 hashCode
  private static Method m1;   //============> Object类中的 equals
  private static Method m2;   // ============> Object类中的 toString
  private static Method m3;   // =============> 实现了接口中 addUser 方法
 
 static
  {
     try
    {
   m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
       m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
   m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
       m3 = Class.forName("com.sxt.target2.TargetClassInteterface").getMethod("addUser", new Class[] { Class.forName("java.lang.String") });
       return;
    }
     catch (NoSuchMethodException localNoSuchMethodException)
    {
       throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
     catch (ClassNotFoundException localClassNotFoundException)
    {
       throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
   // 创建代理类对象 InvocationHandler 对象 本质上就是传入 ProxyHanlder 自己定义的代理类程序处理器
   
   public $Proxy0(InvocationHandler paramInvocationHandler)
     throws
  {
  // 调用父类的有参构造方法 : 将自己定义 ProxyHanlder 传给Proxy
     super(paramInvocationHandler);
  // 将自己定义的处理器 赋值给了 Proxy 类中 h 成员变量    
  }
   
   public final boolean equals(Object paramObject)
     throws
  {
     try
    {
       return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
     catch (Error|RuntimeException localError)
    {
       throw localError;
    }
     catch (Throwable localThrowable)
    {
       throw new UndeclaredThrowableException(localThrowable);
    }
  }
   // 在 测试类中,使用创建出来的代理对象   调用 addUser ,其实就是调用此处的addUser
   public final void addUser(String paramString)
     throws
  {
     try
    {
   // this.h : ProxyHandler对象
   // this.h 当前类中h变量 当前类中没有 h 所以h是从父类 Proxy类继承而来.
   // this.h 就是父类Proxy中h,而Proxy中h ,是自定义的ProxyHandler
   //proxyHandler.invoke(this,m3,paramString); //this : proxy 代理类对象   m3 具体的add方法   paramString 传入的参数
   //调用Proxy Handler的 invoke 方法
   /*
  // 被代理的目标 此时类型时 Object 那么传入任何类型都可以
  private Object proxyTarget;
 
 ?
  public ProxyHanlder(Object proxyTarget) {
  this.proxyTarget = proxyTarget;
  }
 ?
   
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  beginTrancation(); // 开启事务
  //m3 addUser.invoke(obj ,args ) : // 此时的obj :proxyTarget ----> 被代理的具体目标类对象   addUser(String name) { 新增用户 }
  Object obj = method.invoke(proxyTarget, args);
  commitTrancation();
  return obj;
  }
   
   
   */
   
   
       this.h.invoke(this, m3, new Object[] { paramString });
       return;
    }
     catch (Error|RuntimeException localError)
    {
       throw localError;
    }
     catch (Throwable localThrowable)
    {
       throw new UndeclaredThrowableException(localThrowable);
    }
  }
   
   public final String toString()
     throws
  {
     try
    {
       return (String)this.h.invoke(this, m2, null);
    }
     catch (Error|RuntimeException localError)
    {
       throw localError;
    }
     catch (Throwable localThrowable)
    {
       throw new UndeclaredThrowableException(localThrowable);
    }
  }
   
   public final int hashCode()
     throws
  {
     try
    {
       return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
     catch (Error|RuntimeException localError)
    {
       throw localError;
    }
     catch (Throwable localThrowable)
    {
       throw new UndeclaredThrowableException(localThrowable);
    }
  }
   
 ?
 }
 ?

其他相关知识:

invoke(Object obj, Object... args):传递object对象及参数调用该对象对应的方法,然后执行该方法。

 

来源于反射

proxy是所有动态代理的基类

proxy构造方法

     protected Proxy(InvocationHandler h) {
         Objects.requireNonNull(h);
         this.h = h;
    }

源码分析里的h就给了proxy里面的h也就是InvocationHandler

4.什么是Cglib动态代理?

创建被代理类

 package com.sxt.target;
 ?
 /**
  * 被代理的类
  */
 public class TargetClass {
 ?
     public void sing(){
         System.out.println("唱歌");
    }
 }
 ?

创建增强类

 package com.sxt.target;
 ?
 import net.sf.cglib.proxy.MethodInterceptor;
 import net.sf.cglib.proxy.MethodProxy;
 ?
 import java.lang.reflect.Method;
 ?
 /**
  * 方法拦截器
  */
 public class MyMethodIntercepter implements MethodInterceptor {
 ?
 ?
     @Override
     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
         before();
         // obj : 子类对象   ----父类 TargetClass
  // args : 参数
  // cglib的动态代理 不是反射. 使用 索引找到该方法
         Object rs = proxy.invokeSuper(obj, args);
         after();
         return rs;
    }
 ?
     public void before() {
         System.out.println("前置增强");
    }
 ?
     public void after() {
         System.out.println("后置增强");
    }
 }
 ?

代理类

 package com.sxt.target;
 ?
 import net.sf.cglib.proxy.Enhancer;
 ?
 public class Test {
     public static void main(String[] args) {
          System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D://java");
         // 创建增强器
         Enhancer enhancer = new Enhancer();
         // 增强的目标
         enhancer.setSuperclass(TargetClass.class);
         // 使用谁增强
         enhancer.setCallback(new MyMethodIntercepter());
         // 创建代理类
         TargetClass obj = (TargetClass) enhancer.create();
         // 调用方法
         obj.sing();
    }
 }
 ?

输出结果

 CGLIB debugging enabled, writing to ‘D://java‘
 前置增强
 唱歌
 后置增强

生成

 D:\JAVA\com\sxt\target
技术分享图片

技术分享图片

// 获取方法的索引

 package com.target;
 ?
 ?
 import java.lang.reflect.InvocationTargetException;
 ?
 import net.sf.cglib.core.DebuggingClassWriter;
 import net.sf.cglib.reflect.FastClass;
 ?
 public class Test2 {
 
  public static void main(String[] args) {
  System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D://java");
  FastClass create = FastClass.create(TargetClass.class);
  //获取方法的索引
  int index = create.getIndex("sing", new Class[] {});
  //调用方法
  try {
  create.invoke(index, new TargetClass(), null);
  } catch (InvocationTargetException e) {
  e.printStackTrace();
  }
  }
 }
 ?

输出

 唱歌
技术分享图片

技术分享图片技术分享图片

JAVA中的代理,静态代理和动态代理,cglib

原文:https://www.cnblogs.com/youyouluming-xz/p/12182991.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!