好啦,到底J动态代理动态代理开始今天的到底J动态代理动态代理正文。 大家都知道,到底J动态代理动态代理AOP 底层是到底J动态代理动态代理动态代理,而 Java 中的到底J动态代理动态代理动态代理有两种实现方式: 这两者最大的区别在于基于 JDK 的动态代理需要被代理的对象有接口,而基于 Cglib 的到底J动态代理动态代理动态代理并不需要被代理对象有接口。 那么小伙伴们不禁要问,到底J动态代理动态代理Spring 中的到底J动态代理动态代理 AOP 是怎么实现的?是基于 JDK 的动态代理还是基于 Cglib 的动态代理? 先来说结论,Spring 中的到底J动态代理动态代理动态代理,具体用哪种,到底J动态代理动态代理分情况: 如果代理对象有接口,到底J动态代理动态代理就用 JDK 动态代理,到底J动态代理动态代理否则就是到底J动态代理动态代理 Cglib 动态代理。 如果代理对象没有接口,到底J动态代理动态代理那么就直接是到底J动态代理动态代理 Cglib 动态代理。云服务器提供商 来看看这段来自官方文档的说辞: 可以看到,即使在最新版的 Spring 中,依然是如上策略不变。即能用 JDK 做动态代理就用 JDK,不能用 JDK 做动态代理就用 Cglib,即首选 JDK 做动态代理。 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 { @Configuration @EnableAspectJAutoProxy(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true) public static class JdkDynamicAutoProxyConfiguration { } @Configuration @EnableAspectJAutoProxy(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 注解,关于这个注解中的几个属性,高防服务器松哥也来稍微说下: 基于如上介绍,我们很容易看出: 再来看看 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 { @Configuration @EnableAspectJAutoProxy(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) public static class JdkDynamicAutoProxyConfiguration { } @Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { } 可以看到,大部分配置都是一样的,有一个地方不太相同,那就是服务器托管 matchIfMissing 属性的值。可以看到,从 Spring Boot2.0 开始,如果用户什么都没有配置,那么默认情况下使用的是 Cglib 代理。 最后我们写一个简单的例子验证一下我们的想法。 首先创建一个 Spring Boot 项目(本案例使用最新版 Spring Boot,即默认使用 Cglib 代理),加入三个依赖即可,如下: spring-boot-starter-web spring-boot-starter spring-boot-starter-aop 接下来我们创建一个 IUserService 接口,如下: public interface IUserService { void hello(); 然后我们再来创建一个该接口的实现类: @Service public class UserServiceImpl implements IUserService { @Override public void hello() { } 方法不用实现。 再来一个简单的切面: @EnableAspectJAutoProxy @Aspect @Component public class LogAspect { @Before("execution(* org.javaboy.demo.UserServiceImpl.*(..))") public void before(JoinPoint jp) { System.out.println("jp.getSignature().getName() = " + jp.getSignature().getName()); } 最后再来一个简单的测试方法,注入 IUserService 实例: @RestController public class HelloController { @Autowired IUserService iUserService; @GetMapping("/hello") public void hello() { iUserService.hello(); } DBUEG 运行一下,就可以看到 IUserService 是通过 Cglib 来代理的。 如果我们想用 JDK 来代理,那么只需要在 application.properties 中添加如下配置即可: 添加完成后,重新 DEBUG,如下图: 可以看到,已经使用了 JDK 动态代理了。 如果用的是 Spring Boot 1.5.22.RELEASE 这个版本,那么即使不在 application.properties 中添加配置,默认也是 JDK 代理,这个我就不测试了,小伙伴们可以自己来试试。 总结一下: just this。