yuyee

cglib入门

代理为要控制访问的类提供了一种可行的途径,他为目标类引入一个中间层,JDK1.3后也有动态代理,不过性能不是很好,1.6有所加强。
CGLIB是一个强大的代码生成包,在ASM上建立,在一些开源工具中经常可以看到他的身影,比如hibernate,spring。
CGLIB底层通过字节码处理框架ASM来将字节码生成新的类,在spring AOP中不强制使用CGLIB,默认是JDK动态代理。
CGLIB 包情况:
net.sf.cglib.core:底层字节码处理类,大部分与ASM有关。
net.sf.cglib.transform:编译期或运行期和类文件的转换
net.sf.cglib.proxy:实现创建代理和方法拦截器的类
net.sf.cglib.reflect:实现快速放射
net.sf.cglib.util:工具包
net.sf.cglib.beans:javabean相关工具类
通过CGLIB创建动态代理,本质上,他是动态的生成目标类的子类,覆盖目标类所有不是final的方法,并给他们设置好callback,因此,原有类的每个方法调用就会变成自定义的拦截方法。
创建动态代理时通常要用到如下api:net.sf.cglib.proxy.Callback这个接口,他是很关键的一个接口,所有被net.sf.cglib.proxy.Enhancer类调用的回调借口都要继承这个接口
如:public interface MethodInterceptor
extends Callback
{
    /**
     * All generated proxied methods call this method instead of the original method.
     * The original method may either be invoked by normal reflection using the Method object,
     * or by using the MethodProxy (faster).
     * @param obj "this", the enhanced object
     * @param method intercepted Method
     * @param args argument array; primitive types are wrapped
     * @param proxy used to invoke super (non-intercepted method); may be called
     * as many times as needed
     * @throws Throwable any exception may be thrown; if so, super method will not be invoked
     * @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.
     * @see MethodProxy
     */    
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
                               MethodProxy proxy) throws Throwable;

}
这个是基与方法的回调,第一个参数是代理对象,第二个是被拦截的方法对象,第三个是方法参数,第四个是方法的代理对象。
public class MyClass {
public void method1() {
System.out.println("method1");
}

public void method2() {
System.out.println("method2");
}
}
拦截器:
public class MethodInterceptImpl implements MethodInterceptor {

public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println(arg1.getName()+"--intercept");
arg3.invokeSuper(arg0, arg2);// 这里其实也可以用原来的方法对象来执行,但是性能上不如cglib的方法代理类
return null;
}
public class MainTest {
public static void main(String[] args) {
simpleTest();
}

private static void simpleTest() {
Enhancer en = new Enhancer();
en.setCallback(new MethodInterceptImpl());
en.setSuperclass(MyClass.class);
MyClass m = (MyClass) en.create();
m.method1();
m.method2();
}
结果:method1--intercept
method1
method2--intercept
method2
现实项目中可能存在某些需求,比如method1需要拦截,而method2不需要拦截。那我们可以对callback做下选择,使用net.sf.cglib.proxy.CallbackFilter做一些过滤。
public class MethodFilterImpl implements CallbackFilter {

private final static int execute = 0;
private final static int unexecute = 1;

public int accept(Method method) {
String methodName = method.getName();
if("method1".equals(methodName)){
return execute;
}
return unexecute;
}

}

调用的时候需要给callback设置好索引位置,因为accept的返回值就是callbacks数组的索引位置。
private static void filterTest() {
Enhancer en = new Enhancer();
Callback[] callbacks = new Callback[] { new MethodInterceptImpl(),
NoOp.INSTANCE };//这里拦截器的索引位置要与filter里的设置一致
en.setCallbacks(callbacks);
en.setSuperclass(MyClass.class);
en.setCallbackFilter(new MethodFilterImpl());
MyClass m = (MyClass) en.create();
m.method1();
m.method2();
}
这里callbacks[1]这个位置使用了NoOp这个回调接口
public interface NoOp extends Callback
{
    /**
     * A thread-safe singleton instance of the <code>NoOp</code> callback.
     */
    public static final NoOp INSTANCE = new NoOp() { };
}
这个callback其实就是直接把任务委派给这个方法在父类中的实现,其实也等同于没做什么额外的事情
执行结果:method1--intercept
method1
method2
method2 并未被MethodInterceptImpl拦截

}

posted on 2010-10-26 14:27 羔羊 阅读(1008) 评论(1)  编辑  收藏 所属分类: aop

Feedback

# re: cglib入门[未登录] 2011-09-03 12:00 小白

小白到此一游  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: