我们都知道,动态代理和静态代理的目标对象都要实现接口,那么怎么样才能不实现接口就能实现代理呢?
我们可以以子类的方式来实现代理:Ciglib代理
Cglib代理,在内存中构建一个子类对象从而实现对目标对象功能的扩展。
1)JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
2) CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
3)CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
Cglib子类代理:
1)需要引入cglib – jar文件,但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。
2)引入功能包后,就可以在内存中动态构建子类
3)代理的类不能为final, 否则报错。
4) 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法。
在Spring的AOP编程中,
如果加入容器的目标对象有实现接口,用JDK代理;
如果目标对象没有实现接口,用Cglib代理;
下面我们建立一个UserDao类
package cn.qblank.cglib;
/**
* 目标对象
* @author Administrator
*/
public class UserDao {
public void save(){
System.out.println("保存数据");
}
}
package cn.qblank.cglib;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* cglib子类代理工厂
* @author Administrator
*/
public class ProxyFactory implements MethodInterceptor{
//维护目标对象
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
//给目标对象创建代理对象
public Object getProxyInstance(){
//工具类
Enhancer en = new Enhancer();
//设置父类
en.setSuperclass(target.getClass());
//设置回调函数
en.setCallback(this);
//创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("开始事务....");
//执行目标函数
Object returnValue = method.invoke(target, args);
//扩展
System.out.println("提交事务....");
return returnValue;
}
}
然后测试一下
package cn.qblank.cglib;
/**
* 测试
* @author evan_qb
*/
public class Test {
public static void main(String[] args) {
//创建目标对象
UserDao target = new UserDao();
//创建代理对象
UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
proxy.save();
}
}
运行结果: