前言:
上一篇文章我们学习了jdk的动态代理。我们知道jdk的动态代理还是很有缺陷的。比如:jdk动态代理如果缺少接口,就不能进行了。这时,就出现了Cglib。cglib的EnHancer字节码增强器。方便为类做增强。
spring底层在调用AOP时,会先判断这个类是否实现了接口,如果有接口就会调用jdk的动态代理,如果没有则用的是Cglib类代理。
贴代码。用代码来入门:
第一步: 我们需要先准备要被代理的一个类,类中有相关方法。我们这里以书包拿东西和塞东西为例子,add方法只是对代表向书包里加东西。按照正常情况我们还需要检查一下书包里有没满吧?如果那样我们还需要增加一个检查方法,能不能有更好的方法,答案是用cglib来进行。
package com.test.aop;
public class Bag {
public void add() {
System.out.println("往书包里塞东西");
}
public void delete() {
System.out.println("往书包外取东西");
}
}
第二步: 我们开始准备cglib代理类,其中最重要的是getProxy()方法,方法前,我们构建了一个对象Enhancer类允许非接口型创建一个java代理。Enhancer动态创建了被代理类进行拦截的所有方法。
package com.test.aop;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author wen
* cglib对象代理
*/
public class HandlerMethod implements MethodInterceptor {
/*
* 利用enhancer来创建代理类
* */
Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
/**
* 将生成类作为将要扩展的类。原理不懂
*/
enhancer.setSuperclass(clazz);
//将当前类回调,为什么直接写个this? 因为MethodInterceptor这个接口继承自Callback接口,而Callback接口是个接口
//我也不知道为什么这么设计。反正很牛的样子
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始调用method" + "可以在这里做点坏事哟");
/**
* 这里我们可以做一些操作,类似于AOP,前置增强
*
* 例如我在这里开启事务
*/
//调用代理对象
methodProxy.invokeSuper(o, objects);
/**
* 这里我们可以做一些操作,类似于AOP,后置增强
* 完成后,没异常,可以提交事务了
*/
System.out.println("调用结束" + "做完坏事要善后哟");
return null;
}
}
第三步: 进行测试了,简单进行测试,看我们的cglib是否代理成功!
package com.test.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
//多态,new一个真实的对象
Bag bag = new Bag();
//实例化代理类对象
HandlerMethod handlerMethod = new HandlerMethod();
//将被代理的类注入,被enhancer类创建代理
Bag a = (Bag) handlerMethod.getProxy(bag.getClass());
//调用原来的方法
bag.add();
System.out.println("——————完美的分割线——————");
//调用被代理后的方法
a.add();
}
}
测试结果:
总结:
cglib和jdk的动态代理共同构成了spring的Aop。当然这仅仅只是核心部分,还有很多通知之类的也是很值得学习的。小编能力有限暂时先这样介绍。cglib的代理从宏观上看好像真的比jdk动态代理好很多很多,但是小编在查阅资料的时候知道,如果很大的请求量,会导致性能下降,当然,她的缺点是如果类被final标记了。那就不能动态生成代理了。