成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Boot 中的 AOP,到底是 JDK 動態代理還是 Cglib 動態代理?

開發 前端
Spring 中的 AOP,有接口就用 JDK 動態代理,沒有接口就用 Cglib 動態代理。 Spring Boot 中的 AOP,2.0 之前和 Spring 一樣;2.0 之后首選 Cglib 動態代理,如果用戶想要使用 JDK 動態代理,需要自己手動配置。

好啦,開始今天的正文。

大家都知道,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 {

@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 注解,關于這個注解中的幾個屬性,松哥也來稍微說下:

  • 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 {

@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 代理。

3. 實踐

最后我們寫一個簡單的例子驗證一下我們的想法。

首先創建一個 Spring Boot 項目(本案例使用最新版 Spring Boot,即默認使用 Cglib 代理),加入三個依賴即可,如下:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

接下來我們創建一個 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 中添加如下配置即可:

spring.aop.proxy-target-class=false

添加完成后,重新 DEBUG,如下圖:

圖片

可以看到,已經使用了 JDK 動態代理了。

如果用的是 Spring Boot 1.5.22.RELEASE 這個版本,那么即使不在 application.properties 中添加配置,默認也是 JDK 代理,這個我就不測試了,小伙伴們可以自己來試試。

4. 小結

總結一下:

  • Spring 中的 AOP,有接口就用 JDK 動態代理,沒有接口就用 Cglib 動態代理。
  • Spring Boot 中的 AOP,2.0 之前和 Spring 一樣;2.0 之后首選 Cglib 動態代理,如果用戶想要使用 JDK 動態代理,需要自己手動配置。

just this。

責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2023-12-06 08:23:44

代理模式設計模式

2024-09-05 09:35:58

CGLIBSpring動態代理

2021-07-14 11:07:56

AOPJDKCglib

2024-01-04 07:42:44

JavaCGLIBJDK

2025-02-27 00:32:35

2021-04-22 09:58:15

JDK代理動態

2019-11-29 16:21:22

Spring框架集成

2021-07-06 06:39:22

Java靜態代理動態代理

2022-12-26 07:37:23

Nacos代理模式運用場景、

2023-07-05 08:17:38

JDK動態代理接口

2017-05-11 21:30:01

Android動態代理ServiceHook

2022-07-05 14:19:30

Spring接口CGLIB

2011-04-06 11:41:25

Java動態代理

2015-09-22 11:09:47

Java 8動態代理

2009-06-22 15:10:00

java 編程AOP

2020-12-29 05:34:00

動態代理

2012-08-28 10:59:26

JavaJava動態代理Proxy

2022-02-22 22:44:46

接口源碼對象

2011-03-23 10:40:51

java代理模式

2021-12-08 06:53:29

面試動態代理
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩精品视频在线 | 色综合欧美 | 欧美视频免费在线 | 手机三级电影 | 精品欧美一区二区三区久久久小说 | 韩日一区二区 | 一区观看 | 精品国产不卡一区二区三区 | 男插女下体视频 | 一级片免费在线观看 | 亚洲91精品 | 999久久久国产精品 欧美成人h版在线观看 | 99re热这里只有精品视频 | 日韩欧美国产一区二区 | 在线视频91| 国产精品777一区二区 | www97影院| 国产探花在线精品一区二区 | www.国产精品 | 亚洲在线观看视频 | 综合久久久久久久 | 99在线资源 | 国产精品久久久久久久久久久新郎 | 欧美色综合一区二区三区 | 91免费看片| 中文字幕 在线观看 | 亚洲精品乱码久久久久久久久 | 国产剧情一区二区三区 | 日韩亚洲欧美综合 | 精品日韩一区 | 九九综合 | 久久人人网 | 国产日韩精品在线 | 亚洲黄色网址视频 | 国产一区二区三区四区在线观看 | 激情影院久久 | 久久综合一区二区 | 亚洲一区在线日韩在线深爱 | 亚洲成人第一页 | 欧美黑人一区二区三区 | 日日噜噜噜夜夜爽爽狠狠视频, |