java动态代理---面试

代理模式
代理模式在Java中特别常见,如spring AOP功能就是用代理来实现的。代理模式作用是:在不修改被代理对象功能的基础上,通过对代理类进行扩展,进行一些功能上的附加与增强。
一般使用代理模式我们需要先定义一个接口,静态代理只是一种简单的java代码功能扩展。而动态代理利用了反射机制,使用更简单,但背后逻辑…先说明一点,动态代理代理的是接口,而不是类,Proxy类产生的代理对象是Proxy的一个实例,这个实例实现了我们定义的接口

一、静态代理

面向接口的编程,代理类与真实类继承自同一个接口(或者继承某个类)

二、动态代理

它通过java反射机制,获取某个被代理类的所有接口,并创建代理类。接口类和被代理类同上

JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。


代理类需要实现InvocationHandler 接口,invoke()虽然没有被显式调用,但该方法也一定被执行了,对应的三个参数分别传入的是:代理类的实例,method是调用的方法,即需要执行的方法;args是方法的参数;

JDK动态代理

1、因为利用JDKProxy生成的代理类实现了接口,所以目标类中所有的方法在代理类中都有。 
2、生成的代理类的所有的方法都拦截了目标类的所有的方法。而拦截器中invoke方法的内容正好就是代理类的各个方法的组成体。 
3、利用JDKProxy方式必须有接口的存在。 
4、invoke方法中的三个参数可以访问目标类的被调用方法的API、被调用方法的参数、被调用方法的返回类型。

cglib动态代理

1、 CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。 
2、 用CGlib生成代理类是目标类的子类。 
3、 用CGlib生成 代理类不需要接口 
4、 用CGLib生成的代理类重写了父类的各个方法。 
5、 拦截器中的intercept方法内容正好就是代理类中的方法体

spring两种代理方式

1. 若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。 
优点:因为有接口,所以使系统更加松耦合 
缺点:为每一个目标类创建接口

2. 若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。 
优点:因为代理类与目标类是继承关系,所以不需要有接口的存在。 
缺点:因为没有使用接口,所以系统的耦合性没有使用JDK的动态代理好。

动态代理和静态代理区别:

1.可以发现功能与静态代理一样,不同的是静态代理每次都要重写接口中方法,而动态代理使我们免于去重写接口中的方法,着重于去扩展相应的功能或是方法的增强,虽然在此示例中可能看不出,可能看上去比静态代理更复杂,当我们在实际开发环境下,接口中方法很多的时候,就可以发现动态代理的便捷,会大大减少项目中的业务量。

2.JDK代理使用的是反射机制实现aop的动态代理,CGLIB代理使用字节码处理框架asm,通过修改字节码生成子类。所以jdk动态代理的方式创建代理对象效率较高,执行效率较低,cglib创建效率较低,执行效率高

3.JDK动态代理机制是委托机制,具体说动态实现接口类,在动态生成的实现类里面委托hanlder去调用原始实现类方法,CGLIB则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。
 

Spring AOP代理用的到底是CGLIB还是JDK动态代理?

1.默认使用 JDK 动态代理,这样便可以代理所有的接口类型(interface)

2.Spring AOP也支持CGLIB的代理方式。如果我们被代理对象没有实现任何接口,则默认是CGLIB

3.我们可以强制使用CGLIB,指定proxy-target-class = "true" 或者 基于注解@EnableAspectJAutoProxy(proxyTargetClass = true)
 

AOP应用场景:

1.场景一: 记录日志
2.场景二: 监控方法运行时间 (监控性能)
3.场景三: 权限控制
4.场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )
5.场景五: 事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )


动态代理简单例子参考文章:https://blog.csdn.net/weixin_36759405/article/details/82770422

动态代理与静态代理区别简单例子参考文章:https://blog.csdn.net/weixin_43849277/article/details/108291320

希望对你有帮助!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值