代理的基本概念

几个英文单词:
proxy [ˈprɒksi] n.  代理服务器;代表权;代理人,代替物;委托书;
invoke [ɪnˈvəʊk] vt. 乞灵,祈求;提出或授引…以支持或证明;召鬼;借助;
invocation [ˌɪnvəˈkeɪʃn] n.  祈祷;乞求;乞灵;乞求神助;
subject [ˈsʌbdʒɪkt] n. 主题,话题;学科,科目;[哲] 主观; adj. 须服从…的;(在君主等)统治下的; v. 提供,提出;使…隶属;

什么是代理
我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品。关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁(不要钻牛角尖!),也就是说,"委托者"对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就相当于为厂家做了一次对客户群体的"过滤"。
我们把微商代理和厂家进一步抽象,前者可抽象为"代理类",后者可抽象为"委托类(被代理类)"。
通过使用代理,通常有两个优点:

  • 可以隐藏委托类的实现
  • 可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。
代理模式是一种结构型设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
其实方法直接调用就可以完成功能,为什么还要加个代理呢?
原因是采用代理模式可以有效的将具体的实现与调用方进行解耦,通过面向接口进行编程完全将具体的实现隐藏在内部。

更通俗的说,代理解决的问题是:当两个类需要通信时,引入第三方代理类,将两个类的关系解耦,让我们只了解代理类即可,而且代理的出现还可以让我们完成与另一个类之间的关系的统一管理。但是一个前提,代理类和委托类要实现相同的接口,因为代理真正调用的还是委托类的方法。

按照代理的创建时期,可以分为两种:
  • 静态代理:若代理类在程序运行前就已经存在,那么这种代理方式被成为静态代理 。静态代理通常是由程序员在Java代码中定义的, 且代理类和委托类会实现同一接口或是派生自相同的父类。
  • 动态代理:在程序运行时运用反射机制动态创建而成。

静态代理

静态代理的一般实现过程:
  • 首先创建一个接口
  • 然后创建具体实现类来实现这个接口,具体实现类中需要将接口中定义的方法的业务逻辑功能实现
  • 再创建一个代理类同样实现这个接口,代理类中接口的方法只要调用具体类中的对应方法即可

这样,我们在需要使用接口中的某个方法时,直接调用代理类的方法即可,而具体的实现隐藏在了底层。

/**第一步:定义一个接口*/
interface Iuser {void eat(String s);
}/**第二步:创建具体实现类,即被代理类或委托类*/
class UserImpl implements Iuser {@Overridepublic void eat(String s) {System.out.println("我要吃" + s);}
}/**第三步:创建代理类*/
class UserProxy implements Iuser {private Iuser user;//代理类通常只实现一个接口,因为代理类中持有的通常只是接口的引用,而不是某个委托类的直接引用public UserProxy() {this.user = new UserImpl();}public UserProxy(Iuser user) {this.user = user;}@Overridepublic void eat(String s) {System.out.println("静态代理前置内容");user.eat(s);//利用的就是多态的特性,也是面向接口编程的一种典型的体现System.out.println("静态代理后置内容");}
}/**静态代理访问演示*/
public class Test {public static void main(String[] args) {UserProxy proxy = new UserProxy();//或 UserProxy proxy = new UserProxy(new UserImpl())proxy.eat("苹果");}
}

代理类和被代理类都需要实现某个功能接口,代理类里面持有被代理类的引用,代理类可以根据需要添加不同的操作。
静态代理类的优点:客户端不需要知道实现类是什么、怎么做的,而只需知道代理类即可(不要钻牛角尖)。
静态代理类的缺点:

  • 代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法,但是因为代理类中接口的方法往往是没什么逻辑的,它通常只是调用了委托类的同名方法而已,所以这就出现了大量重复、冗余的代码。
  • 如果接口中增加或修改了某个方法,除了所有委托类需要修改代码外,所有代理类也需要修改代码,增加了代码维护的复杂度。
  • 代理对象只服务于一种类型的对象,即静态代理类只能为特定的接口服务,如想要为多个接口服务则需要建立多个代理类,这在大型系统中大大增加了复杂度。

动态代理

静态代理是在编译时就将接口、实现类、代理类一股脑儿全部手动完成,但如果我们需要很多的代理,每一个都这么手动的去创建实属浪费时间,而且会有大量的重复代码,此时我们就可以采用动态代理。
动态代理可以在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能,主要用的是JAVA的反射机制。
也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的"指示"动态生成的。
/**第一步:定义一个接口*/
interface Iuser {void eat(String s);
}/**再定义一个接口*/
interface Irun {String run(int length);
}/**第二步:创建具体实现类,即被代理类或委托类*/
class UserImpl implements Iuser, Irun {@Overridepublic void eat(String s) {System.out.println("我要吃" + s);}@Overridepublic String run(int length) {System.out.println("我跑了 " + length + " 米");return "跑步很欢乐";}
}/**第三步:定义代理实例的【调用处理器】,这是一个位于代理类与委托类之间的【中介类】,它需要实现【InvocationHandler】接口*/
class UserHandler implements InvocationHandler {private Object object;//调用处理器持有委托类的引用,但并不限定委托类必须是某一接口或某一类public UserHandler(Object object) {//这里是用Object接收的,所以可以传递任何类型的对象this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object returnObj = method.invoke(object, args); //【核心点】通过反射执行某个类的某方法System.out.println("【方法】" + method.getName() + "【参数】" + Arrays.toString(args) + "【返回值】" + returnObj);return returnObj;}
}/**第四步:在使用时动态创建动态代理类*/
public class Test {public static void main(String[] args) {test1();System.out.println("----------------------2---------------------");test2();System.out.println("----------------------3---------------------");test3();}private static void test1() {//完全基于接口Iuser的用法Iuser user = new UserImpl();System.out.println("【委托类】" + user.getClass().getName());//UserImplSystem.out.println("【委托类实现的接口】" + Arrays.toString(user.getClass().getInterfaces()));//[interface Iuser, interface Irun]InvocationHandler handler = new UserHandler(user);Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[] { Iuser.class }, handler);//可以直接强转为IuserSystem.out.println("【代理类实现的接口】" + Arrays.toString(proxy.getClass().getInterfaces()));//[interface Iuser]。因为你只指定了Iuser接口proxy.eat("苹果");}private static void test2() {//精简形式Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[] { Iuser.class }, new UserHandler(new UserImpl()));System.out.println("【代理类实现的接口】" + Arrays.toString(proxy.getClass().getInterfaces()));//[interface Iuser, interface Irun]proxy.eat("香蕉你个巴拉");}private static void test3() {//完全基于委托类UserImpl,之所以采用这种方式,是因为委托类实现了多个接口,且我们需要调用不同接口中的方法Object proxy = Proxy.newProxyInstance(UserImpl.class.getClassLoader(), UserImpl.class.getInterfaces(), new UserHandler(new UserImpl()));((Iuser) proxy).eat("你妹");//可以强转为IuserString returnObj = ((Irun) proxy).run(99);//也可以强转为IrunSystem.out.println(returnObj);}
}

动态代理的实现其实与静态代理类似,都需要创建代理类,但是不同之处也很明显,创建方式不同!不同之处体现在静态代理我们知根知底,我们知道要对哪个接口、哪个实现类来创建代理类,所以我们在编译前就直接实现与实现类相同的接口,直接在实现的方法中调用实现类中的相应同名方法即可;而动态代理不同,我们不知道它什么时候创建,也不知道要创建针对哪个接口、实现类的代理类(因为它是在运行时因需实时创建的)。

动态代理用到的两个类
proxy instance:代理实例,即代理类的实例,指得是通过 Proxy.newProxyInstance 产生的对象
the invocation handler of a proxy instance:代理实例的调用处理器,指的是实现InvocationHandler接口的那个中介类

接口 InvocationHandler 调用处理器

java.lang.reflect.InvocationHandler

InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
InvocationHandler是代理实例的调用处理器实现的接口。
PS:InvocationHandler的实现类并不是代理类,而只是位于代理类与委托类之间的中介类。
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
每个代理实例都具有一个关联的调用处理器。对代理实例调用方法时,将对方法调用进行编码,并将其指派到,它的调用处理器的 invoke 方法。
换一种语气描述就是:每个代理类的实例都关联到了一个实现InvocationHandler接口的handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。
唯一的一个方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; //在代理实例上处理方法调用并返回结果。

在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
参数:
  • proxy - 在其上调用方法的代理实例
  • method - 对应于在代理实例上调用的接口方法的 Method 实例。 Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
  • args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类的实例中。
返回:
  • 从代理实例的方法调用返回的值。
  • 如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。
  • 如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出 NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出 ClassCastException。

Proxy 动态代理类

public class java.lang.reflect.Proxy extends Object implements java.io.Serializable

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

基本简介

创建某一接口 Foo 的代理:
InvocationHandler handler = new MyInvocationHandler(new FooImpl());//FooImpl是实现 Foo 接口的某一委托类
Foo f = (Foo) Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class }).getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });

或使用以下更简单的方法:
Foo proxy = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),//定义了由哪个ClassLoader对象来对生成的代理对象进行加载new Class[] { Foo.class },//表示的是我将要给我需要代理的对象提供一组什么接口,之后我这个代理对象就会实现了这组接口handler);//表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的 调用处理程序 对象,它可以实现接口InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。

代理类具有的属性(properties)

A proxy class has the following properties:
  • 代理类是公共的、最终的,而不是抽象的。Proxy classes are public, final, and not abstract.
//这句话我觉得是有问题的,如下:
System.out.println("【代理类的修饰符】" + Modifier.toString(proxy.getClass().getModifiers()));//final,并不是public的

  • 未指定代理类的非限定名称 The unqualified name of a proxy class is unspecified。但是,以字符串 "$Proxy" 开头的类名空间应该为代理类保留。
System.out.println("【代理类】" + proxy.getClass().getName());//【$Proxy0】

  • 代理类的超类为(A proxy class extends) java.lang.reflect.Proxy。
System.out.println("【代理类的超类】" + proxy.getClass().getSuperclass());//【class java.lang.reflect.Proxy】

  • 代理类会按同一顺序准确地实现其创建时指定的接口。
  • 如果代理类实现了非公共接口,那么它将在与该接口相同的包中定义。If a proxy class implements a non-public interface, then it will be defined in the same package as that interface. 否则,代理类的包也是未指定的 unspecified。注意,包密封 package sealing 将不阻止代理类在运行时在特定包中的成功定义,也不会阻止相同类加载器和带有特定签名的包所定义的类。
  • 由于代理类将实现所有在其创建时指定的接口,所以对其 Class 对象调用 getInterfaces 将返回一个包含相同接口列表的数组(按其创建时指定的顺序),对其 Class 对象调用 getMethods 将返回一个包括这些接口中所有方法的 Method 对象的数组,并且调用 getMethod 将会在代理接口中找到期望的 as would be expected 一些方法。
System.out.println("【代理类实现的接口】" + Arrays.toString(proxy.getClass().getInterfaces()));//[interface Iuser, interface Irun]

  • 如果 Proxy.isProxyClass 方法传递代理类(由 Proxy.getProxyClass 返回的类,或由 Proxy.newProxyInstance 返回的对象的类),则该方法返回 true,否则返回 false。
System.out.println("【是否是代理类】" +Proxy.isProxyClass(proxy.getClass()));//true

  • 代理类的 java.security.ProtectionDomain 与由引导类加载器(如 java.lang.Object)加载的系统类相同,原因是代理类的代码由受信任的系统代码生成。此保护域通常被授予 java.security.AllPermission。
  • 每个代理类都有一个可以带一个参数(接口 InvocationHandler 的实现)的公共构造方法,用于设置代理实例的调用处理程序。并非必须使用反射 API 才能访问公共构造方法,通过调用 Proxy.newInstance 方法(将调用 Proxy.getProxyClass 的操作和调用带有调用处理程序的构造方法结合在一起)也可以创建代理实例。

代理实例具有的属性

  • 提供代理实例 proxy 和一个由其代理类 Foo 实现的接口,表达式 proxy instanceof Foo 将返回 true,并且 (Foo) proxy 的强制转换操作将会成功(而不抛出 ClassCastException):
//指定代理类实现的接口为:new Class[] { Iuser.class, Irun.class }
((Iuser) proxy).eat("苹果");//可以强转为Iuser
((Irun) proxy).run(99);//也可以强转为Irun

  • 每个代理实例都有一个关联的调用处理程序,它会被传递到其构造方法中。静态 Proxy.getInvocationHandler 方法将返回与作为其参数传递的代理实例相关的调用处理程序。
Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[] { Iuser.class }, handler);
System.out.println(Proxy.getInvocationHandler(proxy) == handler);//true

  • 代理实例上的接口方法调用将按照该方法的文档描述进行编码,并被指派到调用处理程序的 Invoke 方法。
  • 在代理实例上的 java.lang.Object 中声明的 hashCode、equals 或 toString 方法的调用将按照与编码和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的 invoke 方法,如上所述。传递到 invoke 的 Method 对象的声明类是 java.lang.Object。代理类不重写从 java.lang.Object 继承的代理实例的其他公共方法,所以这些方法的调用行为与其对 java.lang.Object 实例的操作一样。

在多代理接口中重复的方法

Methods Duplicated in Multiple Proxy Interfaces
当代理类的两个或多个接口包含一个具有相同名称和参数签名的方法时,代理类的接口顺序变得非常重要。在代理实例上调用重复方法时,传递到调用处理程序的 Method 对象没有必要成为其声明类可以从接口(通过该接口调用代理方法)的引用类型指派的对象。此限制存在的原因是,生成的代理类中的相应方法实现无法确定它通过哪一个接口调用。因此,在代理实例上调用重复方法时,第一个接口中的方法的 Method 对象包含接口的代理类列表中的方法(直接或通过超级接口继承),该对象会传递到调用处理程序的 invoke 方法,无论该方法调用通过哪一种引用类型发生。
如果代理接口包含某一方法,它的名称和参数签名与 java.lang.Object 的 hashCode、equals 或 toString 方法相同,那么在代理实例上调用这样的方法时,传递到调用处理程序的 Method 对象将使 java.lang.Object 成为其声明类。换句话说,java.lang.Object 公共的非最终方法理论上在所有代理接口之前,以便确定哪一个 Method 对象传递到调用处理程序。
还要注意,当重复方法被指派到调用处理程序时,invoke 方法只可以抛出经过检查的异常类型,该异常类型可以使用所有 代理接口(可以通过它调用)中方法的 throws 子句指派一种异常类型。如果 invoke 方法抛出一个经过检查的异常,该异常没有指派给任何由一个代理接口(可以通过它调用)中的方法声明的异常类型,那么该代理实例上的调用将抛出一个未经检查的 UndeclaredThrowableException。此限制表示并非所有的由传递到 invoke 方法的 Method 对象上调用 getExceptionTypes 返回的异常类型都可以由 invoke 方法成功抛出。

API

字段
  • protected InvocationHandler  h  此代理实例的调用处理程序。
构造方法
  • protected Proxy(InvocationHandler h)  使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例。
公共方法
  • static InvocationHandler    getInvocationHandler(Object proxy)  返回指定代理实例的调用处理程序。
  • static boolean    isProxyClass(Class<?> cl)  当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。
  • static Class<?>    getProxyClass(ClassLoader loader, Class<?>... interfaces)  返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。
  • static Object    newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
    • 返回值:一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
    • 参数:
  • loader - 定义代理类的类加载器。定义了由哪个ClassLoader对象来对生成的代理对象进行加载
  • interfaces - 代理类要实现的接口列表。表示的是我将要给我需要代理的对象提供一组什么接口,之后我这个代理对象就会实现了这组接口
  • h - 指派方法调用的调用处理程序。表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

关于 newProxyInstance 方法

为什么我们可以将newProxyInstance方法返回的Object类型的对象转化为Iuser或Irun类型的对象?
原因就在newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现这组接口,这个时候我们当然可以将这个代理对象强制类型转化为这个接口的对象。
另外,通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它实际的类型并不是我们的 InvocationHandler 类型,也不是我们定义的那组接口的类型,而是在运行时动态生成的一个对象,并且命名方式都是这样的形式,以$开头,Proxy为中,最后一个数字表示对象的标号。
我们来看看这两句:
((Iuser) proxy).eat("苹果");
((Irun) proxy).run(99);

这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的 handler 中的 invoke 方法去执行,而我们的这个 handler 对象又接受了一个 UserImpl 类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用 handler 中的 invoke 方法去执行。

CGLIB代码生成库简介

主页:https://github.com/cglib/cglib
wiki地址:https://github.com/cglib/cglib/wiki 
jar包下载地址、源码下载地址
Byte Code Generation Library is high level API to generate and transform JAVA byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access.
字节码生成库是用于生成和转换JAVA字节码的高级API。它被AOP,测试,数据访问框架用于生成动态代理对象并拦截字段访问。

JDK从1.3版本起就提供了一个动态代理,它使用起来非常简单,但是有个明显的缺点:需要目标对象实现一个或多个接口。
通常来说,你可以使用JDK动态代理方法来创建代理,对于没有接口的情况或者性能因素,CGLIB是一个很好的选择。
使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB简单易用,且它的运行速度要远远快于JDK的Proxy动态代理。本质上来说,CGLIB通过产生子类覆盖非final方法来进行代理,CGLIB不能代理一个final类或者final方法。
CGLIB是一个强大的、高性能的代码生成库。它被广泛使用在基于代理的AOP框架(例如Spring AOP和dynaop)提供方法拦截。Hibernate作为最流行的ORM工具也同样使用CGLIB库来代理单端关联(集合懒加载除外,它使用另外一种机制)。EasyMock和jMock作为流行的Java测试库,它们提供Mock对象的方式来支持测试,都使用了CGLIB来对没有接口的类进行代理。
在实现内部,CGLIB库使用了ASM这一个轻量但高性能的字节码操作框架来转化字节码,产生新类。除了CGLIB,像Groovy和BeanShell这样的脚本语言同样使用ASM来生成Java字节码。ASM使用了一个类似于SAX分析器的机制来达到高性能。我们不建议直接使用ASM,因为这样需要对JVM非常了解,包括类文件格式和指令集。

CGLIB API
API文档详见:http://cglib.sourceforge.net/apidocs/index.html 
CGLIB库组织如下所示:
  • net.sf.cglib.core:底层字节码操作类;大部分与ASP相关。
  • net.sf.cglib.transform:编译期、运行期的class文件转换类。
  • net.sf.cglib.proxy:代理创建类、方法拦截类。
  • net.sf.cglib.reflect:更快的反射类、C#风格的代理类。
  • net.sf.cglib.util:集合排序工具类
  • net.sf.cglib.beans:JavaBean相关的工具类
对于创建动态代理,大部分情况下你只需要使用proxy包的一部分API即可。

一个案例
import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;interface LoginService {public boolean checkUser();
}class LoginServiceImpl implements LoginService {@Overridepublic boolean checkUser() {System.out.println("LoginServiceImpl  checkUser");return false;}
}interface UserService {public String getUserName();
}class UserServiceImpl implements UserService {@Overridepublic String getUserName() {System.out.println("UserServiceImpl getUserName");return null;}}class CglibProxy implements MethodInterceptor {@Overridepublic Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {System.out.println("*********代理方法执行前************");Object retObj = methodProxy.invokeSuper(proxy, params);System.out.println("*********代理方法执行后************");return retObj;}//返回目标对象的代理对象  public Object newProxy(Object target) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass());enhancer.setCallback(this);enhancer.setClassLoader(target.getClass().getClassLoader());return enhancer.create();}
}public class Test {public static void main(String[] args) {//创建目标对象  LoginService loninService = new LoginServiceImpl();UserService userService = new UserServiceImpl();CglibProxy proxy = new CglibProxy();//创建代理对象  LoginService loninService$Proxy = (LoginService) proxy.newProxy(loninService);UserService userService$Proxy = (UserService) proxy.newProxy(userService);loninService$Proxy.checkUser();userService$Proxy.getUserName();}
}

2017-9-6
来自为知笔记(Wiz)

转载于:https://www.cnblogs.com/baiqiantao/p/7485704.html

Proxy 代理模式 动态代理 CGLIB相关推荐

  1. 【设计模式】代理模式 ( 动态代理 | 模拟 Java 虚拟机生成对应的 代理对象 类 )

    文章目录 前言 一.模拟 JVM 生成对应的 代理对象 二.模拟 JVM 生成对应的 代理对象 完整流程展示 1.目标对象接口 2.被代理对象 3.调用处理程序 4.模拟 JVM 生成的代理对象类 5 ...

  2. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  3. 【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )

    文章目录 前言 一.静态代理的弊端 二.动态代理的优势 三.动态代理使用流程 1.目标对象接口 2.被代理对象 3.调用处理程序 4.客户端 四.动态生成 代理对象 类 的 字节码 文件数据 前言 代 ...

  4. 【设计模式】代理模式 ( 动态代理 )

    文章目录 一.动态代理使用流程 二.动态代理代码示例 1.订单类 2.Service 接口 3.Service 实现类 4.Service 静态代理类 5.Dao 接口 6.Dao 实现类 7.Ser ...

  5. Java设计模式-之代理模式(动态代理)

    一.简介 1.什么叫代理模式:        简而言之就是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

  6. 代理模式(动态代理)

    动态代理.就是不用自己写代理类,只要实现接口就行了. 动态代理,这里介绍两种:jdk and cglib 第一个jdk //一个接口类 public interface Book{void read( ...

  7. Spring AOP中的静态代理和动态代理的原理和实践

    对于最近博主最近写博客的兴致大发,我也在思考:为什么而写博客?在互联网时代,无论你是牛人大咖,还是小白菜鸟,都有发表自己看法的权利.无论你是对的还是错的,都会在这个平台上找到答案.所以,我会尽可能去写 ...

  8. 代理模式——静态代理,动态代理(JDK代理和CGLib代理)

    概述 由于某些原因需要给某对象提供一个代理以控制对该对象的访问. 这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. Java中的代理按照代理类生成时机不同又分为 ...

  9. 代理模式 静态代理、JDK动态代理、Cglib动态代理

    1 代理模式 使用代理模式时必须让代理类和被代理类实现相同的接口: 客户端通过代理类对象来调用被代理对象方法时,代理类对象会将所有方法的调用分派到被代理对象上进行反射执行: 在分派的过程中还可以添加前 ...

最新文章

  1. MOS2010开发基础和集几种开发模型
  2. 汽车与智能家居互联时代 语音控制很关键
  3. ReactiveCocoa的使用方法
  4. Python :集合推导式和字典推导式
  5. 的文件夹结构_Windows中你需要知道的目录结构 「第一期」
  6. tsm如何备份oracle原理,征文:TSM备份Oracle脚本及策略说明
  7. 设置 git/npm/bower/gem 镜像或代理的方法
  8. Java Web乱码分析及解决方式(一)——GET请求乱码
  9. 在Windows mobile 5.0下操作INI文件
  10. 开源 免费 java CMS - FreeCMS1.5-数据对象-info
  11. Cocos2d-x特殊节点对象(瓦片地图、粒子系统、视差滚动)概述
  12. python转视频格式高清_树莓派环境下使用python将h264格式的视频转为mp4
  13. windows bat命令启动python程序
  14. DSD, DFF, DSF, DST概念解析
  15. 时钟周期,机器周期(cpu周期),指令周期,存储周期,总线周期
  16. 一行JS代码实现ie浏览器升级弹窗
  17. POI导出读取Excel表格讲解
  18. 【LiteApp系列】爱奇艺小程序架构浅析
  19. 【Jquery-03】jq中的样式操作
  20. 统计中的p-value检验

热门文章

  1. 消息称网易取代九城拿下《魔兽》内地代理权
  2. “灰太狼的羊”事件惹争议,关联商标被抢注
  3. 一文看懂互动视频的发展、应用及创新
  4. 智慧树知到期末答案python_2020智慧树知到Python程序设计基础(山东联盟)期末答案...
  5. matlab中syms怎么替代,科学网—Matlab中的syms与conj - 孔令才的博文
  6. 数据安全性强制存取控制
  7. 【工业通讯】CAN基础内容详解(二)——物理层
  8. Git基础(二)本地Git仓库管理
  9. 5 个不常提及的 HTML 技巧
  10. Photoshop 批量照片转格式