jdk动态代理和cglib jdk 区别动态代理的区别

博客分类:
1、代理的概念
为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以
用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
&&&&&
&&&&&&&&& 功能:负责请求的预处理、过滤、执行完请求后续处理,使得委托类专注于业务处理.SpringAOP就是采用的这种模式
A1、根据代理类的生成时间不同,分为静态代理和动态代理.此处所讲为JDK代理,主要运用java的反射机制
(1)所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
&&& Begin--------&生成步骤:&&&
&&&&&& a首先业务接口 SubJect
&&&&&& b然后委托类实现:RealSubject
&&&&&& c再者:建立代理类,拥有一个委托类对象,然后重写方法,其中重写方法调用委托类的方法,并且可以做一些前置和后续处理
&&&&&& d最后:建立代理对象的访问方式,一般是通过静态:static ProxyClass getInstance();
&&&&&& End----------&
&&&&&&
(2)动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。
&&&&&&&& 代理类和委托类的关系是在程序运行时确定。
&&& Begin--------&生成步骤:
&&& a. 实现InvocationHandler接口创建自己的调用处理器---&主要是对委托类的一些方法进行处理封装,其内部通常包含指向委托类
&&&&&&&&&&&&&&&& 实例的引用,用于真正执行分派转发过来的方法调用&
&& InvocationHandler handler = new InvocationHandlerImpl(..);&&
&&& b. 给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类
&& Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });&&
&&& c. 以调用处理器类型为参数,利用反射机制得到动态代理类的构造函数
&&&&&&&& Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });&&
&&& d. 以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象
&&&&&&&& Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });&
&&&&&&& 其中:Proxy类的静态方法newProxyInstance对上面具体步骤的后三步做了封装,简化了动态代理对象的获取过程。
&&& a.InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发&
&& InvocationHandler handler = new InvocationHandlerImpl(..);&&
&&& b.通过 Proxy 直接创建动态代理类实例&
&& Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,new Class[] { Interface.class },& handler );
&&& End----------&
(3)、优缺点比较:
& X1:静态代理类优缺点
& Advantage:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
& Disadvantage:
& a.代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
& b.如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
& X2:动态代理类优缺点
& Advantage:最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,
&&&&&&&&&& 在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。此处的外围业务类似类似Spring AOP
& Disadvantage:无法对Class进行动态代理,因为所有代理类有共同的父类:Proxy,由于不能进行多继承。
&&&&
A2、另外一种常用代理为cglib代理,基于类的动态代理,cglib动态代理底层是借助asm来实现的,而asm在生成类之后的相关执行过程中比较高效
& (可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)
(1)
&& Begin-------------&生成步骤:
&& a.需要实现MethodInterceptor接口,实现intercept方法。该代理中在委托类方法前后加入了自定义的切面逻辑,委托类方法的执行语句为:
&&&& proxy.invokeSuper(object, args);
&& b.获取增强的目标类的工厂Factory,其中增强的方法类对象是有Enhancer来实现的
&&&& RealSubject realSubject = (RealSubject) enhancer.create();&
&& End-------------&
&&
& cglib代理和jdk代理的区别:
& jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有
& 一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
& 相对来说,动态代理的实现更简单一些。
总结:
代理类和委托类都要去实现一个接口。以接口为桥梁实现代理。
代理类中设置接口为句柄属性,并提供setter方法。并构造一个带参(接口句柄)的构造器。覆盖接口中的方法中编写代理逻辑(之前或之后)。
测试---& 接口 接口句柄& =&& new 代理类(new 委托类());
* 代理接口。处理给定名字的任务。
public interface Subject {
* 执行给定名字的任务。
* @param taskName
public void dealTask(String taskName);
public void test2(String s);
* 真正执行任务的类,实现了代理接口。 也叫委托类
public class RealSubject implements Subject {
* 执行给定名字的任务。这里打印出任务名,并休眠500ms模拟任务执行了很长时间
* @param taskName
public void dealTask(String taskName) {
System.out.println("正在执行任务:" + taskName);
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
public void test2(String s) {
System.out.println("123" + s);
动态代理处理类
* 动态代理类对应的调用处理程序类
public class SubjectInvocationHandler implements InvocationHandler {
// 代理类持有一个委托类的对象引用
public SubjectInvocationHandler(Object delegate) {
this.delegate =
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long stime = System.currentTimeMillis();
// 利用反射机制将请求分派给委托类处理。Method的invoke返回Object对象作为方法执行结果。
// 因为示例程序没有返回值,所以这里忽略了返回值处理 ,这里method类似于一个对所有方法的描述..
Object object = method.invoke(delegate, args);
long ftime = System.currentTimeMillis();
System.out.println("执行任务耗时" + (ftime - stime) + "毫秒");
动态工厂及测试
* 生成动态代理对象的工厂.
public class DynProxyFactory {
// 客户类调用此工厂方法获得代理对象。
// 对客户类来说,其并不知道返回的是代理类对象还是委托类对象。
public static Subject getInstance() {
Subject delegate = new RealSubject();
// InvocationHandler相当于对某个指定对象所有方法包括构造器的一个封装,通过InvocationHandler可以指定调用哪个方法...
InvocationHandler handler = new SubjectInvocationHandler(delegate);
Subject proxy =
// proxy = Proxy.newProxyInstance(loader, interfaces, h);
proxy = (Subject) Proxy
.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(), handler);
public static void main(String[] args) {
// DynProxyFactory.getInstance().dealTask("DBQueryTask");
DynProxyFactory.getInstance().test2("china");
// Class cls = Proxy.getProxyClass(new
// RealSubject().getClass().getClassLoader(), Subject.class);
// System.out.println(cls.getName());
// System.out.println(Proxy.isProxyClass(cls));
执行任务耗时1毫秒
Mr_White_b
浏览: 450 次
来自: 北京
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'&关于动态代理和静态代理
当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象。
按照代理对象的创建时期不同,可以分为两种:
静态代理:事先写好代理对象类,在程序发布前就已经存在了;
动态代理:应用程序发布后,通过动态创建代理对象。
静态代理其实就是一个典型的代理模式实现,在代理类中包装一个被代理对象,然后影响被代理对象的行为,比较简单,代码就不放了。
其中动态代理又可分为:JDK动态代理和CGLIB代理。
1.JDK动态代理
此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。
代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。
JDK动态代理只能针对实现了接口的类生成代理。
2.CGLIB代理
CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,
主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。
JDK动态代理和CGLIB代理生成的区别
JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。
PS:final 所修饰的数据具有&终态&的特征,表示&最终的&意思:
final 修饰的类不能被继承。
final 修饰的方法不能被子类重写。
final 修饰的变量(成员变量或局部变量)即成为常量,只能赋值一次。
final 修饰的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有 一次赋值的机会,而且只能在构造方法中显式赋值,然后才能使用。
final 修饰的局部变量可以只声明不赋值,然后再进行一次性的赋值。
public Object createProxyObject(Object obj) {
this.targetObject =
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
return proxyO// 返回代理对象,返回的对象其实就是一个封装了&实现类&的代理类,是实现类的实例。
public Object newProxy(Object targetObject) {// 将目标对象传入进行代理
this.targetObject = targetO
//注意这个方法的参数,后面是类实现的接口
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);// 返回代理对象
在代码中可以看到,在生成代理类时,传递的是实现类所实现的接口 targetObject.getClass().getInterfaces(),所以JDK只能对于接口进行做代理。如果换成类的话,则会抛java.lang.ClassCastException异常。&
在Spring的源码中,可以看到很多生成代理类的代码。
动态代理的应用
AOP(Aspect-OrientedProgramming,面向切面编程),AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作。
实现AOP的技术,主要分为两大类:
一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建&方面&,从而使得编译器可以在编译期间织入有关&方面&的代码。
Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。
默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。
如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入&aop:aspectj-autoproxy proxy-target-class="true"/&)。
阅读(...) 评论()&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
Spring中JDK动态代理和CGLIB动态代理的性能比较
摘要:新项目开始之前领导让研究下公司原有的框架(基于struts1.2.9+spring2.0.6),比较古老了。读service基类时发现竟然将request穿透到了service层(request为BaseService的实例变量),这样service就变成了有状态Bean,使service层变成了非线程安全,导致用Spring容器管理service的时候不得不使用prototype的scope我们知道,service由于要做事务的包装,需要创建代理对象,spring中使用JD
新项目开始之前领导让研究下公司原有的框架(基于struts1.2.9+spring2.0.6),比较古老了。读service基类时发现竟然将request穿透到了service层(request为BaseService的实例变量),这样service就变成了有状态Bean,使service层变成了非线程安全,导致用Spring容器管理service的时候不得不使用prototype的scope
我们知道,service由于要做事务的包装,需要创建代理对象,spring中使用JDK动态代理或者CGLIB动态代理来创建代理对象,据说JDK动态代理创建对象的时间快于CGLIB,但是性能比CGLIB差(接下来我会测试这个观点),所以我得出以下结论:
1.spring在bean的scope为prototype的情况下,因为是延迟实例化bean,所以最好使用JDK的API创建代理对象;
2.反之对于singleton对象,spring默认是容器启动时就初始化bean,最好使用CGLIB来创建对象
把service配置成singleton我觉得性能方面显然要更好些,如果非要将request穿透到service层,是不是可以考虑用ThreadLocal?
在测试之前,我们先确定spring是以什么方式使用JDK动态代理和CGLIB的,如图:
JDK动态代理:
CGLIB动态代理:
接下来对测试下JDK动态代理和CGLIB动态代理的性能(CGLIB测试代码也和spring一样使用MethodInterceptor)
先贴上测试代码
public interface CountService { int count();}
public class CountServiceImpl implements CountService { private int count = 0; public int count() { return ++ }}
import java.io.Fimport java.io.FileNotFoundEimport java.io.FileOutputSimport java.io.IOEimport java.lang.reflect.InvocationHimport java.lang.reflect.Mimport java.lang.reflect.Pimport java.text.DecimalFimport net.sf.cglib.core.DefaultGeneratorSimport net.sf.cglib.proxy.Eimport net.sf.cglib.proxy.MethodIimport net.sf.cglib.proxy.MethodP@SuppressWarnings(&unused&)public class DynamicProxyPerformanceTest { public static void main(String[] args) throws Exception { CountService delegate = new CountServiceImpl(); long time = System.currentTimeMillis(); CountService jdkProxy = createJdkDynamicProxy(delegate); time = System.currentTimeMillis() - System.out.println(&Create JDK Proxy: & + time + & ms&); time = System.currentTimeMillis(); CountService cglibProxy = createCglibDynamicProxy(delegate); time = System.currentTimeMillis() - System.out.println(&Create CGLIB Proxy: & + time + & ms&); for (int i = 0; i & 3; i++) { test(jdkProxy, &Run JDK Proxy: &); test(cglibProxy, &Run CGLIB Proxy: &); System.out.println(&-------------------&); } } private static void test(CountService service, String label) throws Exception { service.count(); // warm up int count = ; long time = System.currentTimeMillis(); for (int i = 0; i & i++) { service.count(); } time = System.currentTimeMillis() - System.out.println(label + time + & ms, & + new DecimalFormat().format(count * 1000 / time) + & t/s&); } private static CountService createJdkDynamicProxy(final CountService delegate) { CountService jdkProxy = (CountService) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] { CountService.class }, new JdkHandler(delegate)); // 反汇编字节码用,测试的时候注释掉这段代码,不然影响测试结果 // 下面一行代码参照java.lang.reflect.Proxy// byte[] proxyClassFile =// sun.misc.ProxyGenerator.generateProxyClass(// jdkProxy.getClass().getName(), jdkProxy.getClass().getInterfaces());// try {// FileOutputStream fos =// new FileOutputStream(new File(jdkProxy.getClass().getName() + &.class&));// fos.write(proxyClassFile, 0, proxyClassFile.length);// } catch (FileNotFoundException e) {// e.printStackTrace();// } catch (IOException e) {// e.printStackTrace();// } return jdkP } private static class JdkHandler implements InvocationHandler { final O JdkHandler(Object delegate) { this.delegate = } public Object invoke(Object object, Method method, Object[] objects) throws Throwable { return method.invoke(delegate, objects); } } private static CountService createCglibDynamicProxy(final CountService delegate) throws Exception { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(CountServiceImpl.class); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return proxy.invokeSuper(obj, args); } }); CountServiceImpl cglibProxy = (CountServiceImpl) enhancer.create(); // 反汇编字节码用,测试的时候注释掉这段代码,不然影响测试结果 // 下面一行代码参照net.sf.cglib.core.AbstractClassGenerator类中byte[] b = strategy.generate(this);// byte[] proxyClassFile = new DefaultGeneratorStrategy().generate(enhancer);// try {// FileOutputStream fos =// new FileOutputStream(new File(cglibProxy.getClass().getName() + &.class&));// fos.write(proxyClassFile, 0, proxyClassFile.length);// } catch (FileNotFoundException e) {// e.printStackTrace();// } catch (IOException e) {// e.printStackTrace();// } return cglibP }}
数据为执行三次,每次调用一千万次代理方法的结果
测试环境1:
JDK:fastdebug1.6
CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar
CPU:PGHz 2.53GHz
测试结果1:
Create JDK Proxy: 13 msCreate CGLIB Proxy: 201 msRun JDK Proxy: 1571 ms, 897,559 t/sRun CGLIB Proxy: 824 ms, 1,711,244 t/s-------------------Run JDK Proxy: 1519 ms, 928,285 t/sRun CGLIB Proxy: 576 ms, 2,448,030 t/s-------------------Run JDK Proxy: 1546 ms, 912,073 t/sRun CGLIB Proxy: 590 ms, 2,389,941 t/s-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢15倍,执行速度是JDK Proxy的2倍左右
测试环境2:
JDK:fastdebug1.7
CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar
CPU:PGHz 2.53GHz
测试结果2:
Create JDK Proxy: 14 msCreate CGLIB Proxy: 204 msRun JDK Proxy: 1608 ms, 876,906 t/sRun CGLIB Proxy: 529 ms, 2,665,530 t/s-------------------Run JDK Proxy: 1591 ms, 886,276 t/sRun CGLIB Proxy: 405 ms, 3,481,642 t/s-------------------Run JDK Proxy: 1624 ms, 868,266 t/sRun CGLIB Proxy: 405 ms, 3,481,642 t/s-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢15倍,执行速度是JDK Proxy的4倍左右
测试环境3:
JDK:jdk1.6.0_21
CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar
CPU:PGHz 2.53GHz
测试结果3:
Create JDK Proxy: 8 msCreate CGLIB Proxy: 99 msRun JDK Proxy: 911 ms, 1,547,821 t/sRun CGLIB Proxy: 435 ms, 3,241,529 t/s-------------------Run JDK Proxy: 870 ms, 1,620,764 t/sRun CGLIB Proxy: 399 ms, 3,533,998 t/s-------------------Run JDK Proxy: 894 ms, 1,577,254 t/sRun CGLIB Proxy: 404 ms, 3,490,260 t/s-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢10倍以上,执行速度是JDK Proxy的2倍左右
测试环境4:
JDK:jdk1.7.0_02
CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar
CPU:PGHz 2.53GHz
测试结果4:
Create JDK Proxy: 43 msCreate CGLIB Proxy: 129 msRun JDK Proxy: 940 ms, 1,500,069 t/sRun CGLIB Proxy: 299 ms, 4,715,937 t/s-------------------Run JDK Proxy: 921 ms, 1,531,015 t/sRun CGLIB Proxy: 269 ms, 5,241,878 t/s-------------------Run JDK Proxy: 932 ms, 1,512,945 t/sRun CGLIB Proxy: 265 ms, 5,321,001 t/s-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢3倍,执行速度是JDK Proxy的3倍以上
字节码比较:
把测试代码中被注释的部分打开,生成class文件后执行javap -c 类名
JDK动态代理生成的字节码:
public final int count() Code: 0: aload_0 1: getfield #16 // Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationH 4: aload_0 5: getstatic #50 // Field m3:Ljava/lang/reflect/M 8: aconst_null 9: invokeinterface #28, 4 // InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/OLjava/lang/reflect/M[Ljava/lang/O)Ljava/lang/O 14: checkcast #52 // class java/lang/Integer 17: invokevirtual #55 // Method java/lang/Integer.intValue:()I 20: ireturn 21: athrow 22: astore_1 23: new #42 // class java/lang/reflect/UndeclaredThrowableException 26: dup 27: aload_1 28: invokespecial #45 // Method java/lang/reflect/UndeclaredThrowableException.&&init&&:(Ljava/lang/T)V 31: athrow Exception table: from to target type 0 21 21 Class java/lang/Error 0 21 21 Class java/lang/RuntimeException 0 21 22 Class java/lang/Throwable
CGLIB生成的字节码:
public final int count(); Code: 0: aload_0 1: getfield #37 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodI 4: dup 5: ifnonnull 17 8: pop 9: aload_0 10: invokestatic #41 // Method CGLIB$BIND_CALLBACKS:(Ljava/lang/O)V 13: aload_0 14: getfield #37 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodI 17: dup 18: ifnull 52 21: aload_0 22: getstatic #43 // Field CGLIB$count$0$Method:Ljava/lang/reflect/M 25: getstatic #45 // Field CGLIB$emptyArgs:[Ljava/lang/O 28: getstatic #47 // Field CGLIB$count$0$Proxy:Lnet/sf/cglib/proxy/MethodP 31: invokeinterface #53, 5 // InterfaceMethod net/sf/cglib/proxy/MethodInterceptor.intercept:(Ljava/lang/OLjava/lang/reflect/M[Ljava/lang/OLnet/sf/cglib/proxy/MethodP)Ljava/lang/O 36: dup 37: ifnonnull 45 40: pop 41: iconst_0 42: goto 51 45: checkcast #55 // class java/lang/Number 48: invokevirtual #58 // Method java/lang/Number.intValue:()I 51: ireturn 52: aload_0 53: invokespecial #35 // Method CountServiceImpl.count:()I 56: ireturn
本文参照了 http://javatar.iteye.com/blog/814426
大小: 14.7 KB
大小: 18.7 KB
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
为您提供0门槛上云实践机会
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
Spring中JDK动态代理和CGLIB动态代理的性能比较相关信息,包括
的信息,所有Spring中JDK动态代理和CGLIB动态代理的性能比较相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International动态代理jdk和cglib的区别 - 3池 - 博客园
学习来源贴:http://www.cnblogs.com/jqyp/archive//1805041.html
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,而JDK是采用反射方式获取委托对象。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
JDK动态代理示例:&1、BookFacade.java&
package net.battier.
public interface BookFacade {
public void addBook();
2、BookFacadeImpl.java&
package net.battier.dao.
import net.battier.dao.BookF
public class BookFacadeImpl implements BookFacade {
public void addBook() {
System.out.println("增加图书方法。。。");
、BookFacadeProxy.java
package net.battier.
import java.lang.reflect.InvocationH
import java.lang.reflect.M
import java.lang.reflect.P
* JDK动态代理代理类
* @author student
public class BookFacadeProxy implements InvocationHandler {
* 绑定委托对象并返回一个代理类
* @param target
public Object bind(Object target) {
this.target =
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
//要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
* 调用方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=
System.out.println("事物开始");
//执行方法
result=method.invoke(target, args);
System.out.println("事物结束");
3、TestProxy.java&
package net.battier.
import net.battier.dao.BookF
import net.battier.dao.impl.BookFacadeI
import net.battier.proxy.BookFacadeP
public class TestProxy {
public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
Cglib动态代理&JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。&
CGLIB动态代理示例:&
1、BookFacadeCglib.java&
package net.battier.
public interface BookFacade {
public void addBook();
2、BookCadeImpl1.java&
package net.battier.dao.
* 这个是没有实现接口的实现类
* @author student
public class BookFacadeImpl1 {
public void addBook() {
System.out.println("增加图书的普通方法...");
3、BookFacadeProxy.java&
package net.battier.
import java.lang.reflect.M
import net.sf.cglib.proxy.E
import net.sf.cglib.proxy.MethodI
import net.sf.cglib.proxy.MethodP
* 使用cglib动态代理
* @author student
public class BookFacadeCglib implements MethodInterceptor {
* 创建代理对象
* @param target
public Object getInstance(Object target) {
this.target =
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
4、TestCglib.java&
package net.battier.
import net.battier.dao.impl.BookFacadeImpl1;
import net.battier.proxy.BookFacadeC
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();

我要回帖

更多关于 jdk代理和cglib 的文章

 

随机推荐