CGLIB-Spring的一种反射机制

 

Spring 在进行反射时候主要有两种策略,一种是直接用 JDK 的反射,另外是用 CgLib

cglib是一个开源项目, 是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO字节码的动态生成。cglib项目主页: http://cglib.sourceforge.net/

CgLib 底层用的 asm

CGLIB-Spring的一种反射机制_第1张图片

Asm 是一个强大的 Java 字节码生成框架,和 BCEL 或者 SERP 很类似,但是小很多,可以动态修改 java 字节码 .

 

其中最核心的代码为

newProxyInstance (obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), InvocationHandler invocationHandler);

obj.getClass().getInterfaces() 可以看出,如果直接用 JDK 的反射需要创建接口,接口是用来搞架构的,但是对于非常非常小的项目去写接口有点麻烦。

CgLib 就可以不用接口,它底层调用 asm 动态生成一个代理类去覆盖父类中非 final 的方法,然后实现 MethodInterceptor 接口的 intercept 方法,这样以后直接调用重写的方法,比 JDK 要快。

但是加载 cglib 消耗时间比直接 jdk 反射时间长,开发的过程中,如果是反复动态生成新的代理类推荐用 jdk 自身的反射,反之用 cglib.

 

Spring Bean 工厂中有一个方法

public void setOptimize (boolean optimize)- 是否使用 CGLIB 代理优化策略 . 仅用于 CGLIB
代理 ; 对于 JDK 动态代理 ( 缺省代理 ) 无效 .


下面是一个 demo( HelloWorld

Jar : cglib-2.2.jar, asm-all-3.1

Helloworld 方法

package com.greysh.cglib;

/**

 * @author Genix.Cao

 */

public class HelloWorld {

       public void say() {

              System.out.println("Hello World");

       }

}

代理类

package com.greysh.cglib;

/**

 * @author Genix.Cao

 */

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {

       @Override

       public Object intercept(Object object, Method method, Object[] args,

                     MethodProxy methodProxy) throws Throwable {

              System.out.println("Before Helloworld~");

        methodProxy.invokeSuper(object, args);

              System.out.println("After Helloworld~");

              return null;

       }

}

测试类

package com.greysh.cglib;

/**

 * @author Genix.Cao

 */

import net.sf.cglib.proxy.Enhancer;

public class TestCglib {

       public static void main(String[] args) {

              Enhancer enhancer = new Enhancer();

           enhancer.setSuperclass(HelloWorld.class);

           enhancer.setCallback(new CglibProxy());

           HelloWorld helloWorld = (HelloWorld) enhancer.create();

           helloWorld.say();

       }

}

Cglib 使用起来学习路线还是很低的

原理是实现 MethodInterceptor 这个接口

System.out.println("Before Helloworld~");

methodProxy.invokeSuper(object, args);

System.out.println("After Helloworld~");

这里就是 AOP 的思想

然后去装载的时候先要生成一个 Enhancer

这个类的作用是先设定被代理类

enhancer.setSuperclass(HelloWorld.class);

然后实例化代理类

enhancer.setCallback(new CglibProxy());

HelloWorld helloWorld = (HelloWorld) enhancer.create();

这样被调用的类就是被 asm 动态改变改变后的类

你可能感兴趣的:(分布式和技术框架们,object,jdk,hibernate,java,class,spring)