1.什么是CGlib?
它是一个开源项目,可以在运行期间扩展Java类与实现Java接口。底层时通过使用一个小而快的字节码的处理nsm架来转换字节码生成新的类。
代理类就是这么通过nsm生成的。
2.应用场景
动态代理其所要增强的目标类可以不实现接口(任何业务接口);当然 亦可以用作实现了的业务接口。
3.代理生成的原理
CGlib使用子类扩展父类的方式来生成代理对象,cglib会自动动态的生成目标类的子类作为代理类,并创建对象,即代理对象。
4.
a.目标类不能是final的。
b.目标类具有自己的参数构造器:如果一个子类具有子类,那么父类就必须拥有无参构造器。
MethodInterceptor (内调接口)——intercept方法————需要创建一个CglibProxy的接口,需要用到Enhancer增强器,借助它来创建代理对象。
5.
当然普通类与动态Proxy的类的区别:
普通类则是预存于一个。class文件中,而Proxy而是在Java.jvm虚拟机中实现运行时动态生成。还有就是CGLIB的动态代理使我们自己写的,而jdk的动态代理直接引用就行。
6.代码展示
(1)以下就是CGlib代理对象 的生成
public interface CglibProxy {
// 用于创建代理对象// targetClass:目标类
// mi:委托类对象
public static Object newProxyInstance(Class targetClass, MethodInterceptor mi) {
// 增强器
Enhancer enhancer = new Enhancer();
// 指定父类,即指定目标类
enhancer.setSuperclass(targetClass);
// 指定回调对象,即指定委托类对象
enhancer.setCallback(mi);
// 创建并返回代理对象
return enhancer.create();
}
(2)// 委托类
public class serviceProxyEntrust implements MethodInterceptor {
// 声明目标对象
// 目标类实现业务接口
/*
private ISomeService target;
public ServiceProxyEntrust(ISomeService target) {
super();
this.target = target;
}
*/
// 目标类没有实现业务接口
private serviceImple target;
public serviceProxyEntrust(serviceImple target2) {
super();
this.target = target2;
}
// 当执行代理对象的代理方法时,代理方法会调用该invoke()方法
// obj:代理对象
// method:目标方法
// args:目标方法参数列表
// proxy:目标方法的代理对象
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
String superName = proxy.getSuperName();
Signature signature = proxy.getSignature();
System.out.println("superName = " + superName);
System.out.println("signature = " + signature);
// 执行目标方法
Object result = method.invoke(target, args);
return result;
}
}
(2)// 客户类
public class Client {
public static void main(String[] args) {
// 创建目标对象
// ISomeService target = new SomeServiceImpl();
serviceImple target = new serviceImple();
// 创建委托对象
serviceProxyEntrust mi = new serviceProxyEntrust(target);
// 创建代理对象
// ISomeService service = (ISomeService) CglibProxy.newProxyInstance(target.getClass(), mi);
serviceImple service = (serviceImple) CglibProxy.newProxyInstance(target.getClass(), mi);
// 调用代理对象的代理方法
String someResult = service.doSome(5, "月份");
System.out.println("someResult = " + someResult);
System.out.println("=========================");
}
}