答:Spring AOP是通过动态代理来实现AOP的
答:代理模式也被称为委托模式
那么什么是代理模式呢?
为其他对象提供一种代理用来控制这个对象的访问,他的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标进行调用,而是提供代理类来间接调用.
作用场景:
在一些特定情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用.
举例:
我们通常情况下的租房,一般是不能直接与房东沟通的,而是通过中介来进行处理租房的相关业务.
代理模式的主要角色:
Subject:业务接口类,可以是抽象类或者接口(定义一些功能,比如租房,买房,交水电费等)
Realsubject:业务实现类,具体的业务执行,也就是被代理对象(房东,继承自subject,以实现父类具有的功能)
Proxy:代理类,也就是代理(中介,同样是继承自subject,以实现父类具有的功能)
代理模式可以在不修改代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强
根据代理的创建时期,代理模式分为静态代理和动态代理
静态代理: 由程序员创建代理类或特定工具自动生成源代码再对其编译, 在程序运行前代理类的 .class 文件就已经存在了(在出租房子之前,中介就已经做好了相关的工作,就等租户来租房子了)
动态代理: 在程序运行时, 运用反射机制动态创建而成,这里spring提供了两种实现方法:JDK,CGLIB.
JDK动态生成代理的实现步骤
1.自定义InvocationHandler
并重写invoke
方法,在invoke
方法中我们会调用目标方法并自定义一些处理逻辑
2.通过Proxy.newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
方法创建对象
1.自定义 MethodInterceptor
并重写intercept
方法,其余同JDK
2.调用Enhancer.create()方法来生成一个代理对象
cglib
cglib
3.3.0
JDK只能实现接口,不能实现类
CJLIB既可以实现接口,也可以实现类
这个可以提够设置来改变proxyTargetClass这个属性来实现,默认值为false.
proxyTargetClass | 目标对象 | 代理方式 |
---|---|---|
false | 实现了接口 | jdk代理 |
false | 未实现接口(只有实现类) | cglib代理 |
true | 实现了接口 | cglib代理 |
true | 未实现接口(只有实现类) | cglib代理 |
可以通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 来设置
注意:
Spring Boot 2.X开始, 默认使用CGLIB代理
可以通过配置项 spring.aop.proxy-target-class=false 来进行修改,设置默认为jdk代理
SpringBoot设置 @EnableAspectJAutoProxy 无效, 因为Spring Boot 默认使用
AopAutoConfiguration进行装配