上一篇文章主要介紹了Spring AOP一些簡單用法,當然如果要了解更多,可以選擇再去看看Spring 文檔。
博主還是喜歡從源碼中知其所以然嘿嘿。
spring-boot-starter-aop
博主以 Spring-boot-starter-aop
爲例,開始分析。
在spring boot
中使用 aop
,我們只需要引入 spring-boot-starter-aop
即可定義註解進行操作:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
從spring-boot-starter-aop
反編譯後的依賴來看,這個項目裏面並沒有任何代碼:
沒有任何代碼,那麼裏面是怎麼引入的呢?抱着這個想法,博主下載了Spring Boot
項目源碼查看,不過裏面確實沒有java
代碼,只有一個gradle
依賴。
dependencies {
api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))
api("org.springframework:spring-aop")
api("org.aspectj:aspectjweaver")
}
在 spring-boot-starter-aop
項目中,引入了一些依賴,包括 spring-aop
和 ajpectjweaver
,以及當前spring-boot
項目的starter
。
經過前面文章也有個大概瞭解,spring-aop
項目中應該只是一些類,而沒有注入到Spring
容器中,那麼 spring-aop
的引線在哪裏呢?
首先要使用spring-boot-starter-aop
,首先得是一個spring-boot
架構項目,而 spring-boot
項目引入依賴的一個途徑是通過增加Spring SPI
配置文件: spring.factories
,有加載 @EnableAutoConfiguration
進行加載,但很明顯,spring-boot-starter-aop
不屬於這一類。
在針對 @SpringBootApplication
進行更細緻分析,它在 spring-boot-autoconfigure
包下面:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
上面 SpringBootApplication
註解中,使用 @ComponentScan
對當前包下進行進一步掃描,此時可以看到有個aop
的子包,下面有個配置類 AopAutoConfiguration
。沒錯,這就是 spring-boot
中,spring-aop
的入口:
@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 {
}
}
@Configuration
說明是配置類,會被spring
掃描到@ConditionalOnClass
即當前classpath下面,有這幾個類EnableAspectJAutoProxy
、Aspect
、Advice
、AnnotatedElement
纔回去加載該類,通俗說就是 即有spring-aop
依賴纔會加載。@ConditionalOnProperty
在上一步,再一步對配置進行條件判斷,即判斷是否有spring.aop.auto
=true
則加載。matchIfMissing = true
或者沒有該配置,則默認加載配置。
類上註解分析完,下面看內部類註解:- spring 代理方式有兩種,一種是jdk代理(需要有接口方式進行代理),一種是cglib方式(不需要接口,以子類方式,但是無法代理final方法)。如上面配置,默認下是使用 cglib進行代理。
下面看兩個子類都有的註解 @EnableAspectJAutoProxy
。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
除了兩個屬性外,還引入了一個 AspectJAutoProxyRegistrar
。 AspectJAutoProxyRegistrar
則爲一個 ImportBeanDefinitionRegistrar
,它將重寫 registerBeanDefinitions
來註冊自己的bean。
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 註冊 AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 設置 EnableAspectJAutoProxy 來的兩個屬性 proxyTargetClass 和 exposeProxy 到 AnnotationAwareAspectJAutoProxyCreator 中
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
- 註冊
AnnotationAwareAspectJAutoProxyCreator
,這是spring-aop
的核心入口類。 - 設置
EnableAspectJAutoProxy
來的兩個屬性proxyTargetClass
和exposeProxy
到AnnotationAwareAspectJAutoProxyCreator
中。
AnnotationAwareAspectJAutoProxyCreator
排除衆多類結構,發現 AnnotationAwareAspectJAutoProxyCreator
是一個 SmartInstantiationAwareBeanPostProcessor
,和解析@Autowired
的類實現同一個接口,大概能猜到,在spring
容器初始化bean
時候,對對應類進行代理操作 。
實現 SmartInstantiationAwareBeanPostProcessor
接口,需要實現以下方法(當然全部有默認接口):
Class<?> predictBeanType(Class<?> beanClass, String beanName)
:預測bean類型Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
解析獲取候選構造方法Object getEarlyBeanReference(Object bean, String beanName)
獲取bean實例,主要目的是解決spring循環依賴Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
實例前處理boolean postProcessAfterInstantiation(Object bean, String beanName)
實例後處理PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
設置一些屬性PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
設置一些屬性值Object postProcessBeforeInitialization(Object bean, String beanName)
實例化前處理Object postProcessAfterInitialization(Object bean, String beanName)
實例化後處理
在 AnnotationAwareAspectJAutoProxyCreator
主要對以下幾個方法有具體實現:
predictBeanType
在AbstractAutoProxyCreator
有實現getEarlyBeanReference
在AbstractAutoProxyCreator
有實現postProcessBeforeInstantiation
在AbstractAutoProxyCreator
有實現postProcessAfterInitialization
在AbstractAutoProxyCreator
有實現
下面從spring容器執行方法先後順序,結合例子具體分析spring-aop
原理。
postProcessBeforeInstantiation
在實例化前進行調用:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 獲取即將緩存名字,有beanName,則返回beanName,如果爲FactoryBean類型,則加上FactoryBean&前綴;沒有beanName,則直接返回beanClass
Object cacheKey = getCacheKey(beanClass, beanName);
// 如果沒有beanName,或者不在 targetSourcedBeans中
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
// 如果已包含該key,則說明已經處理過了
return null;
}
// 如果該bean是spring-aop的框架內部bean,即 Advice,Pointcut,Advisor,AopInfrastructureBean 幾種bean。或者有@Aspect註解,或者,這個bean類,本身就是aspectj創建。 則加入到advisedBeans bean 並跳過。
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
- 獲取即將緩存名字,有beanName,則返回beanName,如果爲FactoryBean類型,則加上FactoryBean&前綴;沒有beanName,則直接返回beanClass。
- 對bean進行處理,判斷是否需要跳過。
isInfrastructureClass
邏輯主要是要跳過以下幾種類型:
- Advice,Pointcut,Advisor,AopInfrastructureBean 幾種bean類型。或者有@Aspect註解,或者,這個bean類,本身就是aspectj創建。
而shouldSkip
主要有以下幾種判斷: - 獲取advisor過程,這個看下一小節
- 如果有一種類型爲
AspectJPointcutAdvisor
則直接跳過 - 執行父類的
shouldSkip
方法,父類主要是 判斷 跳過original instance
類型bean
- 如果有配置
targetSource
,則調用getAdvicesAndAdvisorsForBean
獲取代理接口,並調用創建代理類接口。
findCandidateAdvisors
findCandidateAdvisors
是獲取Advisor
過程:
AnnotationAwareAspectJAutoProxyCreator
的 findCandidateAdvisors
方法:
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
看父類的 AbstractAdvisorAutoProxyCreator
中方法:
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
具體使用 BeanFactoryAdvisorRetrievalHelper
的 findAdvisorBeans
,這個方法主要目的是找到所有 資格的 Advisor
bean類,該方法會忽略 FactoryBean
類型,以及排除 正在創建的bean。
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
// 直接從beanFactory中獲取所有Advisor類。
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
在Spring中,也可以直接使用@Aspect註解,當從 findAdvisorBeans
沒有獲取到信息是,會嘗試調用 BeanFactoryAspectJAdvisorsBuilder
的 buildAspectJAdvisors()
獲取註解。
public List<Advisor> buildAspectJAdvisors() {
// 讀取緩存
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 獲取所有實例,即Object子類。
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
// 判斷是否已經制定表達式過濾
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
// 如果是 @Aspect註解且不是aspectj動態產生的。那額
aspectNames.add(beanName);
// 構造 Aspect 元數據
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// 如果改AspectJ 註解 是單例模型
// 構造一個 BeanFactoryAspectInstanceFactory
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 獲取在Advice 中配置的Advisor,即PointCut信息。
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 單例
this.advisorsCache.put(beanName, classAdvisors);
}
else {
// 非單例
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// 非單例模型
if (this.beanFactory.isSingleton(beanName)) {
// 再一次檢查
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
// 構造MetadataAwareAspectInstanceFactory 並緩存
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
// 從獲取到的有Aspecj 註解的類,進行獲取其 Advisor過程
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
// 構造 MetadataAwareAspectInstanceFactory 並加入
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
整個 findCandidateAdvisors
方法有點長,但是代碼邏輯還是挺容易理解的
- 調用父類方法
findCandidateAdvisors
獲取Advisor
類型類,即實現了Advisor
接口類。Advisor
是Advice
的一個點,實際上爲Advice
的一個切點(JoinPoint)。這個接口一般不建議給Spring 使用者用,而提供給Spring 所需要的的維護者使用。 - 再從
BeanFactoryAspectJAdvisorsBuilder
的buildAspectJAdvisors
中,將所有切面@Advice
從beanFactory解析出,並且分別解析其PointCut
,每個攔截方法,使用Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
註解,就是一個Advisor
。
this.advisorFactory.getAdvisors(factory)
往下看 this.advisorFactory.getAdvisors(factory)
具體內容:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 獲取目標代理類
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 獲取切面名字
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
// 判斷是否爲懶加載切面
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
// 獲取該切面類的切點信息
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
// 對 @DeclareParent 註解進行處理
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
上面代碼中,看對普通增強器獲取,主要方法爲: getAdvisor
:
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 驗證
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 獲取切點
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 包裝一層 InstantiationModelAwarePointcutAdvisorImpl
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
其實對於普通使用 @Aspectj
切面的處理,就是將其切點信息PointCut
獲取出來並處理:
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 獲取Pointcut, Around, Before, After, AfterReturning, AfterThrowing
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 設置poincut信息後取出。
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
上面代碼片段中,對每個方法進行獲取增強器操作,而後封裝爲 InstantiationModelAwarePointcutAdvisorImpl
返回。
InstantiationModelAwarePointcutAdvisorImpl
的構造方法,則是普通信息的填充,而主要是其內部的 instantiateAdvice
,對信息進行初始化過程。
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
再看 ReflectiveAspectJAdvisorFacotory
的 getAdvice
方法:
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 切面類
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 獲取方法上面註解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
// candidateAdviceMethod 爲候選方法,expressionPointcut 爲註解上面切點信息, aspectInstanceFactory 爲
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
根據不同類型AspectJ註解,Spring 封裝了不同類返回。
主要有以下幾種:
@Around
:AspectJAroundAdvice
@Before
:AspectJMethodBeforeAdvice
@After
:AspectJAfterAdvice
@AfterReturning
:AspectJAfterReturningAdvice
@AfterThrowing
:AspectJAfterThrowingAdvice
小結
本文主要分析Spring AOP入口,以及postProcessBeforeInstantiation
部分內容,下文將針對 具體 createProxy
具體分析
覺得博主寫的有用,不妨關注博主公衆號: 六點A君。
哈哈哈,一起研究Spring: