阿里云用ip做网站,wordpress转html,南京哪里有做网站的,东莞哪里有网站建设厂家大家都知道#xff0c;AOP 底层是动态代理#xff0c;而 Java 中的动态代理有两种实现方式#xff1a; 基于 JDK 的动态代理 基于 Cglib 的动态代理
这两者最大的区别在于基于 JDK 的动态代理需要被代理的对象有接口#xff0c;而基于 Cglib 的动态代理并不需要被代理对…大家都知道AOP 底层是动态代理而 Java 中的动态代理有两种实现方式 基于 JDK 的动态代理 基于 Cglib 的动态代理
这两者最大的区别在于基于 JDK 的动态代理需要被代理的对象有接口而基于 Cglib 的动态代理并不需要被代理对象有接口。
那么Spring 中的 AOP 是怎么实现的是基于 JDK 的动态代理还是基于 Cglib 的动态代理 1. Spring 先来说结论Spring 中的动态代理具体用哪种分情况 如果代理对象有接口就用 JDK 动态代理否则就是 Cglib 动态代理。 如果代理对象没有接口那么就直接是 Cglib 动态代理。
来看看这段来自官方文档的说辞 可以看到即使在最新版的 Spring 中依然是如上策略不变。即能用 JDK 做动态代理就用 JDK不能用 JDK 做动态代理就用 Cglib即首选 JDK 做动态代理。 2. Spring Boot Spring Boot 和 Spring 一脉相承那么在动态代理这个问题上是否也是相同的策略呢抱歉这个还真不一样。
Spring Boot 中对这个问题的处理以 Spring Boot2.0 为节点前后不一样。
在 Spring Boot2.0 之前关于 Aop 的自动化配置代码是这样的Spring Boot 1.5.22.RELEASE
Configuration
ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
ConditionalOnProperty(prefix spring.aop, name auto, havingValue true, matchIfMissing true)
public class AopAutoConfiguration {ConfigurationEnableAspectJAutoProxy(proxyTargetClass false)ConditionalOnProperty(prefix spring.aop, name proxy-target-class, havingValue false,matchIfMissing true)public static class JdkDynamicAutoProxyConfiguration {}ConfigurationEnableAspectJAutoProxy(proxyTargetClass true)ConditionalOnProperty(prefix spring.aop, name proxy-target-class, havingValue true,matchIfMissing false)public static class CglibAutoProxyConfiguration {}}
可以看到这个自动化配置主要是在讨论 application.properties 配置文件中的 spring.aop.proxy-target-class 属性的值。
具体起作用的是 ConditionalOnProperty 注解关于这个注解中的几个属性也来稍微说下 prefix配置文件的前缀。 name配置文件的名字和 prefix 共同组成配置的 key。 having期待配置的值如果实际的配置和 having 的值相同则这个配置就会生效否则不生效。 matchIfMissing如果开发者没有在 application.properties 中进行配置那么这个配置类是否生效。
基于如上介绍很容易看出 如果开发者设置了 spring.aop.proxy-target-class 为 false则使用 JDK 代理。 如果开发者设置了 spring.aop.proxy-target-class 为 true则使用 Cglib 代理。 如果开发者一开始就没配置 spring.aop.proxy-target-class 属性则使用 JDK 代理。
这是 Spring Boot 2.0 之前的情况。
再来看看 Spring Boot 2.0含之后的情况Spring Boot 2.0.0.RELEASE
Configuration
ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,AnnotatedElement.class })
ConditionalOnProperty(prefix spring.aop, name auto, havingValue true, matchIfMissing true)
public class AopAutoConfiguration {ConfigurationEnableAspectJAutoProxy(proxyTargetClass false)ConditionalOnProperty(prefix spring.aop, name proxy-target-class, havingValue false, matchIfMissing false)public static class JdkDynamicAutoProxyConfiguration {}ConfigurationEnableAspectJAutoProxy(proxyTargetClass true)ConditionalOnProperty(prefix spring.aop, name proxy-target-class, havingValue true, matchIfMissing true)public static class CglibAutoProxyConfiguration {}}
可以看到大部分配置都是一样的有一个地方不太相同那就是 matchIfMissing 属性的值。可以看到从 Spring Boot2.0 开始如果用户什么都没有配置那么默认情况下使用的是 Cglib 代理。 3. 实践 最后可以写一个简单的例子验证一下上面的理论。
首先创建一个 Spring Boot 项目本案例使用最新版 Spring Boot即默认使用 Cglib 代理加入三个依赖即可如下
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId
/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId
/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId
/dependency
接下来创建一个 IUserService 接口如下
public interface IUserService {void hello();}
然后再来创建一个该接口的实现类
Service
public class UserServiceImpl implements IUserService {Overridepublic void hello() {}}
方法不用实现。
再来一个简单的切面
Aspect
Component
EnableAspectJAutoProxy
public class LogAspect {Before(execution(* org.lzx.demo.UserServiceImpl.*(..)))public void before(JoinPoint jp) {System.out.println(jp.getSignature().getName() jp.getSignature().getName());}}
最后再来一个简单的测试方法注入 IUserService 实例
RestController
public class HelloController {Autowiredprivate IUserService iUserService;GetMapping(/hello)public void hello() {iUserService.hello();}}
DBUEG 运行一下就可以看到 IUserService 是通过 Cglib 来代理的。 如果我们想用 JDK 来代理那么只需要在 application.properties 中添加如下配置即可
spring.aop.proxy-target-classfalse
添加完成后重新 DEBUG如下图 可以看到已经使用了 JDK 动态代理了。
如果用的是 Spring Boot 1.5.22.RELEASE 这个版本那么即使不在 application.properties 中添加配置默认也是 JDK 代理。 4. 小结 总结一下 Spring 中的 AOP有接口就用 JDK 动态代理没有接口就用 Cglib 动态代理。 Spring Boot 中的 AOP2.0 之前和 Spring 一样2.0 之后首选 Cglib 动态代理如果用户想要使用 JDK 动态代理需要自己手动配置。