Code Generation Library动态代理实现
面向切面编程主要使用的就是动态代理:日志,事务,异常监听。。。需要根据异常的类型来决定这个事务是否要回滚还是继续提交。
常用的动态代理有两种,分别是cglib动态代理和jdk自带的动态代理。两种代理模式各有千秋,都有自己的优点可相应的业务场景(如今,性能已经不是我们取决的标准)。
jdk动态代理:基于接口实现,生成的代理对象是实现了被代理对象的接口,动态生成java代码,编译,继而loader进jvm进行 使用。
cglib动态代理:基于被代理对象实现,生成的代理对象是继承了被代理对象的类,在其执行的时候调用invokeSuper来执行其父类方法。
仍然是基于找对象为例进行实现cglib的 动态代理
/*
*被代理对象
* 春申君寻找真爱
*/
public class SpringShenjun {
public void findLove() {
System.out.println("春申君-->寻找真爱");
}
}
//业务处理类 媒婆
//jdk动态代理是我们自己自己传入的拿到被代理对象的引用
//cglib的动态代理是cglib帮我们创建对象的
public class CglibMeimo implements MethodInterceptor{
public Object getInstance(String className) throws Exception{
//用过反射机制,进行实例化
Class<?> forName = Class.forName(className);
Enhancer enhancer = new Enhancer();
//设置父类为谁
//这一步就是告诉cglib,生成的子类需要继承哪个类
enhancer.setSuperclass(forName);
//回调我们的方法intercept(...)
enhancer.setCallback(this);
//第一步:生成源代码
//第二步:编译生成class文件
//第三步:classloader进jvm
return enhancer.create();
}
/**
* 同样是做了字节码重组这样一件事情
* 对于使用 api的用户来说,是无感知的
* @param o
* @param method
* @param objects
* @param methodProxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib媒婆启动");
//调用的super的方法
//这个o的引用是cglib给我们new出来的
//cglib在new出来以后的对象是被代理对象的子类(继承了我们写的那个类)
//在new子类之前,实际上默认先调用了super()方法的
//new了子类的同时,必须先new出来父类,这就相当于简介的持有了我们父类的引用
//子类重写了父类的所有的方法
//我们改变子类对象的某些属性,是可以间接的操作父类的属性
methodProxy.invokeSuper(o, objects);
System.out.println("cglib媒婆匹配成功");
return null;
}
}
//Code Generation Library代码生成库
public class CglibProxyTest {
public static void main(String[] args) throws Exception {
/*
jdk生成的动态代理是通过接口来进行强制转换的
生成以后的代理对象,可以强制转换为接口。
CGLib的动态代理是通过生成一个被代理对象的子类,然后重写父类的方法
生成以后的对象,可以强制转换为被代理对象(也就是用自己写的类)
子类引用赋值类父类
*/
//aop解耦方便了团队的开发
SpringShenjun csj = (SpringShenjun)new CglibMeimo().getInstance("com.csj.cglib.SpringShenjun");
csj.findLove();
}
}
cglib的动态代理是基于动态生成被代理对象的子类来实现的。在应用中,被代理对象若是没有实现了接口,则可以使用该cglib动态代理较为合适方便。也是spring中aop常用 的设计模式之一。