1.JDK动态代理要求目标类实现接口,才能对其进行代理,但是对于没有实现接口的类,可以使用CGLib进行动态代理
2.CGLib采用了非常底层的字节码技术(依靠ASM的jar包,是一种开源的java字节码编辑类库),
其`原理`是通过字节码技术为目标类创建一个子类对象,并在子类对象中拦截所有父类方法的调用,
然后在方法调用前后调用后都可以加入自己想要执行的代码
大白话来说就是:
CGLib采用的方式让`目标对象当父类`,`代理对象为子类`
注:高版本的spring中,已经在spring-core-xx.jar中,把cglib和asm的核心代码整合了进来
目标类,无需实现接口
//目标的对象 没有实现接口
public class BookService {
public void addBook() {
System.out.println("添加书籍成功");
}
}
产生cglib动态代理对象的工厂类,实现MethodInterceptor
生产代理对象
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
//产生cglib动态代理对象的工厂类
public class MyCglibProxyFactory implements MethodInterceptor {
//获得动态代理对象
public Object getInstance(Class<?> c) {//传过来的是目标对象
Enhancer enhancer = new Enhancer();
//设置谁是父类
enhancer.setSuperclass(c);//传过来的是父类
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();//返回代理对象
}
//intercept方法会拦截所有代理对象中方法的调用
//obj 参数:将来生成的代理对象
//method参数:将来代理对象所调用的方法的镜像
//args 参数:将来代理对象调用方法时所传的参数
//proxy参数:该参数可以用来调用到父类中的方法
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//之前
System.out.println("log: "+method.getName()+"开始执行了..");
//调用父类中的方法
Object value = proxy.invokeSuper(obj, args);
//之后
System.out.println("log: "+method.getName()+"方法执行结束..");
return value;
}
}
测试类
public class TestCglibProxy {
public static void main(String[] args) {
//产生cglib的动态代理对象的工厂类
MyCglibProxyFactory factory = new MyCglibProxyFactory();
BookService proxy= (BookService)factory.getInstance(BookService.class);
proxy.addBook();
System.out.println("------------------");
System.out.println(proxy.getClass());
}
}