What:什么是cglib动态代理?
cglib动态代理是由第三方类库实现的代理,使用要添加cglib jar包,其代理底层是借助 asm来实现的。( asm是java虚拟机里面的一种动态生成字节码的技术,跟反射是不同的)
How:怎么实现cglib动态代理呢?
/**
* 目标对象类
*/
public class Target {
public void sayHello() {
System.out.println("你好");
}
}
/**
* cglib动态代理
*/
public class CGLibDynamicProxy implements MethodInterceptor {
//目标对象
private Object target;
/**
* 创建代理对象
* @param target
* @return
*/
public Object getInstance(Object target){
this.target=target;
//用这个类 来创建代理对象(被代理类的子类);并设置父类;设置回调。
//Enhancer该类是cglib jar包中的类
Enhancer enhancer=new Enhancer();
//设置被代理类作为其父类的代理目标
enhancer.setSuperclass(this.target.getClass());
//设置回调方法,当这个代理对象方法被调用时,回调方法intercept()会被执行
enhancer.setCallback(this);
//返回创建的代理对象
return enhancer.create();
}
/**
* 回调方法
* @param o
* @param method
* @param objects
* @param methodProxy 代理的类的方法(会调用父类被代理的方法)
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result=null;
before();//前置增强
result=methodProxy.invokeSuper(o,objects);
after();//后置增强
return result;
}
/**
* 在实现方法前可以做的事情
*/
public void before(){
System.out.println("摘下耳机");
}
/**
* 在实现方法后做的事情
*/
public void after(){
System.out.println("戴上耳机");
}
}
/**
* cglib动态代理测试端
*/
public class CglibProxyTest {
public static void main(String[] args) {
CGLibDynamicProxy cgLibDynamicProxy=new CGLibDynamicProxy();
//生成代理对象
Target hello=(Target) cgLibDynamicProxy.getInstance(new Target());
//当调用代理对象的被代理方法时,会自动回调,调用CGLibDynamicProxy代理类中的Intercept()方法
hello.sayHello();
}
}
控制台输出:
摘下耳机
你好
戴上耳机
Process finished with exit code 0
Why:为什么要用cglib动态代理?
因为jdk动态代理只能代理实现了接口的类,如果该目标类没有实现任何接口,则不能使用jdk动态代理,可以看下WHWW之代理模式(2)-动态代理。而cglib动态代理是针对类来实现的,也就是说这个目标类可以不用实现任何接口,cglib动态代理都可以对该类进行代理。
注:因为cglib动态代理采用的是继承,所以不能对final修饰的类进行代理
Where:哪些地方使用cglib动态代理?
spring Aop的底层实现就用到cglib动态代理,如果我们要对没有实现接口的类进行功能扩展时,也可以考虑cglib动态代理。