Springboot Actuator之十二:actuator aop

前言
spring 中aop是一個核心概念,spring boot 是如何實現自動化配置的?如今咱們就來分析一下java

解析
spring boot 中自動化配置是讀取/META-INF/spring.factories 中讀取org.springframework.boot.autoconfigure.EnableAutoConfiguration配置的值,其中有關aop的只有一個,即org.springframework.boot.autoconfigure.aop.AopAutoConfiguration.該類就是打開寶箱的鑰匙spring

AopAutoConfiguration 聲明瞭以下註解:ui

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
1
2
3
@Configuration –> 配置類
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class }) –> 在當前的類路徑下存在EnableAspectJAutoProxy.class, Aspect.class, Advice.class時該配置才被解析
@ConditionalOnProperty(prefix = 「spring.aop」, name = 「auto」, havingValue = 「true」, matchIfMissing = true) –> 當配置有spring.aop.auto= true時生效.若是沒有配置,則默認生效
AopAutoConfiguration中只有2個內部類:.net

JdkDynamicAutoProxyConfiguration,代碼以下:scala

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true)
public static class JdkDynamicAutoProxyConfiguration {代理

}
1
2
3
4
5
6
@Configuration –> 配置類
@EnableAspectJAutoProxy(proxyTargetClass = false) –> 開啓aop註解,關於該註解,後面有解析.
@ConditionalOnProperty(prefix = 「spring.aop」, name = 「proxy-target-class」, havingValue = 「false」, matchIfMissing = true)–> 當配置有spring.aop.proxy-target-class= false時生效,若是沒有配置,默認生效.
CglibAutoProxyConfiguration,代碼以下:對象

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = false)
public static class CglibAutoProxyConfiguration {blog

}
1
2
3
4
5
6
@Configuration –> 配置類
@EnableAspectJAutoProxy(proxyTargetClass = false) –> 開啓aop註解
@ConditionalOnProperty(prefix = 「spring.aop」, name = 「proxy-target-class」, havingValue = 「true」, matchIfMissing = false)–> 當配置有spring.aop.proxy-target-class= true時生效,若是沒有配置,默認不生效.
所以,咱們能夠知道,aop 默認生效的JdkDynamicAutoProxyConfiguration.這也符合咱們關於spring aop的認知,默認是使用jdk,若是使用面向類的代理,則須要配置spring.aop.proxy-target-class=true,來使用cglib進行代理接口

@EnableAspectJAutoProxy 代碼以下:事務

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

// 代表是否使用基於類的代理,false--> 使用面向接口的代理(java 動態代理).true--> 使用cglib
boolean proxyTargetClass() default false;

// 代表是否暴露代理(經過ThreadLocal的方式),該屬性設置爲true可解決目標對象內部的自我調用將沒法實施切面中的加強的問題.
boolean exposeProxy() default false;
}
1
2
3
4
5
6
7
8
9
10
11
12
關於目標對象內部的自我調用將沒法實施切面中的加強的問題可看Spring事務處理時自我調用的解決方案及一些實現方式的風險 這篇博客

這裏經過@Import(AspectJAutoProxyRegistrar.class),導入了AspectJAutoProxyRegistrar的配置.

仍是由以前的文章可知,此時會調用ConfigurationClassParser#processImports.因爲AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar接口,所以會加入到JdkDynamicAutoProxyConfiguration所對應的ConfigurationClass 的importBeanDefinitionRegistrars中.

最後,在ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars會對importBeanDefinitionRegistrars依次調用其registerBeanDefinitions 方法.

AspectJAutoProxyRegistrar#registerBeanDefinitions 代碼以下:

public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
註冊id爲org.springframework.aop.config.internalAutoProxyCreator,class 爲 AnnotationAwareAspectJAutoProxyCreator的bean.這裏通過層層調用,最終調用AopConfigUtils#registerOrEscalateApcAsRequired方法,代碼以下:

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 若是已經存在了自動代理建立器且存在的自動代理建立器與現狀的不一致那麼須要根據優先級來判斷到底須要使用哪個
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
// 改變bean最重要的就是改變bean所對應的ClassName
apcDefinition.setBeanClassName(cls.getName());
}
}
// 若是已經存在自動代理建立器而且與將要建立的一致,那麼無需再次建立
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
這裏傳入的cls 爲AnnotationAwareAspectJAutoProxyCreator.class
若是已經存在了自動代理建立器且存在的自動代理建立器與現狀的不一致那麼須要根據優先級來判斷到底須要使用哪個–> 若是此時傳入的AnnotationAwareAspectJAutoProxyCreator的優先級比已註冊的優先級高,則替換爲AnnotationAwareAspectJAutoProxyCreator.而後直接return
若是已經存在自動代理建立器而且與將要建立(AnnotationAwareAspectJAutoProxyCreator)的一致,那麼無需再次建立
進行註冊,id爲org.springframework.aop.config.internalAutoProxyCreator,class 爲 AnnotationAwareAspectJAutoProxyCreator,優先級爲Integer.MIN_VALUE.角色爲內部使用
若是配置了proxyTargetClass等於true,則對id爲org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition 添加proxyTargetClass 的屬性,值爲true.代碼以下:

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
1
2
3
4
5
6
若是配置了exposeProxy等於true,則對id爲org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition 添加exposeProxy 的屬性,值爲true. 代碼以下:

public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);}}123456關於aop方面的源碼,筆者準備在spring深度揭祕中一一道來,關於spring boot 中的aop 自動化配置就解析到這裏.--------------------- 版權聲明:本文爲CSDN博主「一個努力的碼農」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。原文連接:https://blog.csdn.net/qq_26000415/article/details/79010971

相關文章
相關標籤/搜索