目录
CGLIB 动态代理
JDK的动态代理机制只能代理实现了接口的类。而不能实现接口的类就不能使用JDK的动态代理,CGLIB是针对类来实现代理的,它的原理是对指定目标类生成一个子类,并覆盖其中的方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
简单结构:
实现原理:继承思想
代理类继承目标类,重写目标类中的方法,
CGLIB像是一个拦截器,在调用我们的代理类方法时,代理类(子类)会去找到目标类(父类),此时它会被一个方法拦截器所拦截,在拦截器中才会去实现方法的调用。并且还会对方法进行行为增强。
简单实现
添加依赖
在pom.xml文件中引入CGLIB的相关依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
定义类
实现MethodInterceptor接口
package org.example.proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Cglib implements MethodInterceptor {
//准备一个目标对象
private Object target;
//通过构造器传入目标对象
public Cglib(Object target) {
this.target = target;
}
/*
* 用来获取代理对象(创建一个代理对象)
* */
public Object getProxy(){
//可以通过Enhancer对象中的create()方法可以去生成一个类,用于生成代理对象
Enhancer enhancer=new Enhancer();
//设置父类(将目标类作为代理类的父类)
enhancer.setSuperclass(target.getClass());
//设置拦截器(回调对象为本身对象)
enhancer.setCallback(this);
//生成一个代理类对象并返回给调用着
return enhancer.create();
}
/*
* 拦截器
* 1.目标对象的方法调用
* 2.行为增强
* 参数 o: cglib 动态生成的代理类的实例
* method:实体类所调用的都被代理的方法的引用
* objects 参数列表
* methodProxy:生成的代理类对方法的代理引用
* */
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//增强行为
System.out.println("方法执行前的增强行为");
//调用目标类中的方法
Object Objectss= methodProxy.invoke(target,objects);
//增强行为
System.out.println("方法执行后的增强行为");
return null;
}
}
定义一个test()类
package org.example.proxy;
public class test3 {
public static void main(String[] args) {
//得到目标对象
You you=new You();
//得到代理类
Cglib cglib=new Cglib(you);
//得到代理对象
Marry marry= (Marry) cglib.getProxy();
//通过代理对象调用目标对象的方法
marry.toMarry();
}
}
那我们来了解一下CGLIB的实现流程
我们最终是要通过一个代理对象去调用方法的,那我们就要获取一个代理对象,
CGLIB代理,是通过Enhancer这个类里面对应的一个create()方法,去生成一个代理对象的。
那么咱们就先创建一个Enhancer对象,拿到这个对象之后,虽然我们是要获取一个代理对象,但你要获取谁的代理对象?咱们是不是要知道。而前面提到CGLIB体现的是继承思想,所以我们需要把代理类作为我们目标类的一个子类,也就是把目标类设置为父类,代理类去继承它。
//设置父类(将目标类作为代理类的父类)
enhancer.setSuperclass(target.getClass());
在你获取代理对象之前,我们应该知道目标对象是谁吧?
获取目标对象,我们还是通过带参构造传进来的。
//准备一个目标对象
private Object target;
//通过构造器传入目标对象
public Cglib(Object target) {
this.target = target;
}
目标对象有了,通过Enhancer代理对象也有了。那么我们创建的类为什么要实现MethodInterceptor接口?
在上图中我们说过会有一个拦截器,MethodInterceptor就是起到的一个拦截作用,在你调用目标类的方法后,它就会被我们的一个拦截器所拦截。
实现MethodInterceptor接口就必须重写intercept方法
/*
* 拦截器
* 1.目标对象的方法调用
* 2.行为增强
* 参数 o: cglib 动态生成的代理类的实例
* method:实体类所调用的都被代理的方法的引用
* objects 参数列表
* methodProxy:生成的代理类对方法的代理引用
* */
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//增强行为
System.out.println("方法执行前的增强行为");
//调用目标类中的方法
Object Objectss= methodProxy.invoke(target,objects);
//增强行为
System.out.println("方法执行后的增强行为");
return Objectss;
}
在intercept方法中我们用methodProxy.invoke(参1,参2);调用目标类中的方法。两个参数分别为目标对象,方法中的参数
JDK代理与CGLIB代理的区别
- JDK动态代理实现接口,CGLIB动态继承思想
- JDK动态代理(目标对象存在接口时)执行效率高于CIGLIB
- 如果对象有接口实现,选择JDK代理,如果没有接口实现选择CGILB代理