按照代理的建立时期,代理类能够分为两种。
静态代理:由程序员建立或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态建立而成。java
动态代理实现有三种方式,jdk动态代理(基于接口),cglib动态代理(基于继承),javassist(hibernate中使用这种方式)实现动态代理。程序员
JDK实现动态代理须要实现类经过接口定义业务方法,对于没有接口的类,如何实现动态代理呢?
这就须要CGLib了。框架
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即便代理类没有实现任何接口也能够实现动态代理功能。maven
CGLib原理是经过字节码技术为一个类建立子类,并在子类中采用方法拦截的技术拦截全部父类方法的调用,顺势织入横切逻辑。ide
CGLib建立的动态代理对象性能比JDK建立的动态代理对象的性能高很多,可是CGLib在建立代理对象时所花费的时间却比JDK多得多,因此对于单例的对象,由于无需频繁建立对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,因为CGLib因为是采用动态建立子类的方法,对于final方法,没法进行代理。工具
下面演示一个动态代理的实例。性能
cglib 是基于asm 字节修改技术。导入 cglib 会间接导入 asm, ant, ant-launcher 三个jar 包。测试
<!-- cglib 动态代理依赖 begin --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.5</version></dependency> <!-- cglib 动态代理依赖 stop -->
CGLIB的核心类:优化
public class HelloService { public HelloService() { System.out.println("HelloService构造"); } public void sayHello() { System.out.println("HelloService:sayHello"); }
net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它常常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;编码
方法拦截器 实现 MethodInterceptor 接口:
public class HelloServiceInterceptor implements MethodInterceptor{ /** * sub:cglib生成的代理对象 * method:被代理对象方法 * objects:方法入参 * methodProxy: 代理方法 */ @Override public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("======插入前置通知======"); Object object = methodProxy.invokeSuper(sub, objects); System.out.println("======插入后置通知======"); return object; }
测试类,生成CGLIB代理对象调用目标方法:
public class CglibTest { public static void main(String[] args) { // 经过CGLIB动态代理获取代理对象的过程 Enhancer enhancer = new Enhancer(); // 设置enhancer对象的父类 enhancer.setSuperclass(HelloService.class); // 设置enhancer的回调对象 enhancer.setCallback(new HelloServiceInterceptor()); // 建立代理对象 HelloService proxy= (HelloService)enhancer.create(); // 经过代理对象调用目标方法 proxy.sayHello(); } }