代码改变世界

java cglib动态代理原理及样例

2014-04-16 23:05  每天努力一点点  阅读(1203)  评论(0编辑  收藏  举报


cglib动态代理:

http://blog.csdn.net/xiaohai0504/article/details/6832990

一、原理

      代理为控制要访问的目标对象提供了一种途径。当访问对象时,它引入了一个间接的层。JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理。JDK的动态代理用起来非常简单,当它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?现在我们可以使用CGLIB包。

二、什么是cglib

     CGLIB是一个强大的高性能的代码生成包。

      1>它广泛的被许多AOP的框架使用,例如:Spring AOP和dynaop,为他们提供方法的interception(拦截);

       2>hibernate使用CGLIB来代理单端single-ended(多对一和一对一)关联(对集合的延迟抓取,是采用其他机制实现的);

       3>EasyMock和jMock是通过使用模仿(moke)对象来测试java代码的包。

     它们都通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。

三、底层

      CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM(Java字节码操控框架),来转换字节码并生成新的类。除了CGLIB包,脚本语言例如 Groovy和BeanShell,也是使用ASM来生成java的字节码。当不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。所以cglib包要依赖于asm包,需要一起导入。


四、样例

1. java方式代理

package cn.jerry.mouse.dynamic_proxy.java;  
  
public interface IStudent {  
    public void action();  
}  


package cn.jerry.mouse.dynamic_proxy.java;  
  
public class StudentImpl implements IStudent
{  
    @Override  
    public void action() {  
       System.out.println("[Student]实际方法。。。");  
    }  
  
}  

package cn.jerry.mouse.dynamic_proxy.java;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JDK动态代理代理类
 */
public class JavaProxy implements InvocationHandler {
	private Object target;

	/**
	 * 绑定委托对象并返回一个代理类
	 * 
	 * @param target
	 * @return
	 */
	public Object bind(Object target) {
		this.target = target;
		// 取得代理对象
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), this); // 要绑定接口
	}

	@Override
	/** 
	 * 调用方法 
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = null;
		System.out.println("【java代理】调用实际方法前");
		// 执行方法
		result = method.invoke(target, args);
		System.out.println("【java代理】调用实际方法后");
		return result;
	}

}


package cn.jerry.mouse.dynamic_proxy.java;  

public class TestProxy {  
 
   public static void main(String[] args) {  
        JavaProxy proxy = new JavaProxy();  
        IStudent student = (IStudent) proxy.bind(new StudentImpl());  
        student.action(); 
    }  
}  

2.cglib方式代理


package cn.jerry.mouse.dynamic_proxy.cglib;  
  
public class StudentImpl
{  
    public void action() {  
       System.out.println("[Student]实际方法。。。");  
    }  
}  


package cn.jerry.mouse.dynamic_proxy.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 使用cglib动态代理
 * 
 */
public class CgLibProxy implements MethodInterceptor {
	private Object target;

	/**
	 * 创建代理对象
	 * 
	 * @param target
	 * @return
	 */
	public Object getInstance(Object target) {
		this.target = target;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.target.getClass());
		// 回调方法
		enhancer.setCallback(this);
		// 创建代理对象
		return enhancer.create();
	}

	@Override
	// 回调方法
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		System.out.println("[cglib代理]调用实际方法前");
		proxy.invokeSuper(obj, args);
		System.out.println("[cglib代理]调用实际方法后");
		return null;

	}

}

package cn.jerry.mouse.dynamic_proxy.cglib;

public class TestProxy {

	public static void main(String[] args) {
		CgLibProxy cglib = new CgLibProxy();
		StudentImpl student = (StudentImpl) cglib.getInstance(new StudentImpl());
		student.action();
	}
}


源代码下载:http://download.csdn.net/detail/yinxing2008/7205015