代理
Java 代理
我们常说的代理分为静态代理和动态代理。
静态代理:代码中显式指定代理
动态代理:类比静态代理,可以发现,代理类不需要实现原接口了,而是实现InvocationHandler。
静态代理
因为需要对一些函数进行二次处理,或是某些函数不让外界知道时,可以使用代理模式,通过访问第三方,间接访问原函数的方式,达到以上目的。
弊端
如果要想为多个类进行代理,则需要建立多个代理类,维护难度加大。
仔细想想,为什么静态代理会有这些问题,是因为代理在编译期就已经决定,如果代理发生在运行期,这些问题解决起来就比较简单,所以动态代理的存在就很有必要了。
动态代理
当动态生成的代理类调用方法时,会触发 invoke
方法,在 invoke
方法中可以对被代理类的方法进行增强。
通过动态代理可以很明显的看到它的好处,在使用静态代理时,如果不同接口的某些类想使用代理模式来实现相同的功能,将要实现多个代理类,但在动态代理中,只需要一个代理类就好了。
除了省去了编写代理类的工作量,动态代理实现了可以在原始类和接口还未知的时候,就确定代理类的代理行为,当代理类与原始类脱离直接联系后,就可以很灵活地重用于不同的应用场景中。
继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。
提供了一个使用InvocationHandler作为参数的构造方法。
生成静态代码块来初始化接口中方法的Method对象,以及Object类的equals、hashCode、toString方法
弊端
代理类和委托类需要都实现同一个接口。也就是说只有实现了某个接口的类可以使用Java动态代理机制。但是,事实上使用中并不是遇到的所有类都会给你实现一个接口。因此,对于没有实现接口的类,就不能使用该机制。
动态代理与静态代理的区别
Proxy类的代码被固定下来,不会因为业务的逐渐庞大而庞大;
代理对象是在程序运行时产生的,而不是编译期;
可以实现AOP编程,这是静态代理无法实现的;
解耦,如果用在web业务下,可以实现数据层和业务层的分离。
动态代理的优势就是实现无侵入式的代码扩展。
静态代理这个模式本身有个大问题,如果类方法数量越来越多的时候,代理类的代码量是十分庞大的。所以引入动态代理来解决此类问题
cglib 是针对类来实现代理的,他的 原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。同样的,final 方法是不能重载的,所以也不能通过CGLIB代理,遇到这种情况不会抛异常,而是会跳过 final
方法只代理其他方法。
CGLIB 代理主要通过对字节码的操作,为对象引入间接级别,以控制对象的访问。 CGLIB 底层使用了ASM(一个短小精悍的字节码操作框架)来操作字节码生成新的类。
CGLIB和Java动态代理的区别
Java 动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为 Proxy,Java 类继承机制不允许多重继承);CGLIB能够代理普通类;
Java 动态代理使用 Java 原生的反射 API 进行操作,在生成类上比较高效;CGLIB 使用 ASM 框架直接对字节码进行操作,在类的执行过程中比较高效
Last updated
Was this helpful?