創建目標類的代理對象過程
步驟1
finishBeanFactoryInitialization(beanFactory), 完成BeanFactory的初始化工作,就是來創建剩下的單實例bean,
在創建的過程中就會被各個后置處理器攔截掉,下面我們就看看finishBeanFactoryInitialization(beanFactory);

步驟2
進入到 finishBeanFactoryInitialization(beanFactory)中,就會看到來到 beanFactory.preInstantiateSingletons()創建bean

進入preInstantiateSingletons()方法中,看到在循環所有bean創建對象,通過getBean(beanName)創建

最后來到doGetBean(name, null, null, false)方法,首先檢查單實例的緩存中是否存在當前對象

如果存在就直接返回,否則就通過調用 getSingleton()獲得單實例bean,只要創建好的bean就會被緩存起來,保證單實例bean

之后調用createBean(beanName,mbd,args)創建bean

進入到createBean()后就會調用resolveBeforeInstantiation(beanName, mbdToUse)方法,
希望后置處理器再此能返回一個代理對象,如果能返回就是使用,否則就調用下面的doCreateBean()創建,對于doCreateBean()方法之前已經詳細介紹過了,
就是先創建bean實例,然后為bean屬性賦值,然后在調用bean的init方法前后調用后置處理器等等操作。

我們來到 resolveBeforeInstantiation(beanName, mbdToUse)中, 給目標對象一個創建一個代理的機會
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 檢查是否尚未確定不需要在實例化前解析
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 確保此時 bean 類已經被解析
// 如果不是合成 bean 且存在 InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 確定目標 bean 的類型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 應用實例化前的 BeanPostProcessor
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 如果成功創建了 bean,則應用初始化后的處理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 標記是否成功在實例化前解析了 bean
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
先調用 applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)方法,進入其中,看到

先循環所有后置處理器,判斷是不是InstantiationAwareBeanPostProcessor類型的后置處理器,
如果是就調用它的postProcessBeforeInstantiation(beanClass, beanName)方法,
而我們之前已經說過AnnotationAwareAspectJAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor類型的后置處理器,
而SmartInstantiationAwareBeanPostProcessor又繼承了InstantiationAwareBeanPostProcessor
所以AnnotationAwareAspectJAutoProxyCreator也就是InstantiationAwareBeanPostProcessor這種類型的后置處理器,
最后就會調用AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation()方法,
我們就來看看postProcessBeforeInstantiation()方法都干了些啥?
步驟3
現在我們就關心我們自己創建的LogAspect和MathCal是怎樣創建的?我們的MathCal來到
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)方法
(AnnotationAwareAspectJAutoProxyCreator中沒有postProcessBeforeInstantiation()方法的實現,只能調用父類的方法),
首先判斷是否在advisedBeans中,advisedBeans中保存了所有需要增強的目標對象bean。第一次創建是不會包含的,所有 if 沒進去。

然后就來到第二個判斷,首先判斷當前bean是否是基礎類型即判斷是否是實現了Advice,Pointcut,Advisor,AopInfrastructureBean
這幾個接口,其次還會判斷是否是加了@Aspect注解的

最后再通過shouldSkip(beanClass, beanName)判斷是否需要跳過
/**
* 判斷是否應該跳過對指定 Bean 類和 Bean 名稱的處理。
*
* @param beanClass Bean 的類對象
* @param beanName Bean 的名稱
* @return 如果應該跳過處理則返回 true,否則返回 false
*/
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 待辦事項:考慮通過緩存切面名稱列表來進行優化
// 查找所有候選的 Advisor(通知器)
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 遍歷所有候選的 Advisor
for (Advisor advisor : candidateAdvisors) {
// 檢查當前 Advisor 是否為 AspectJ 切點通知器
if (advisor instanceof AspectJPointcutAdvisor) {
// 獲取該 Advisor 中的通知,并將其轉換為 AbstractAspectJAdvice 類型
// 然后獲取切面的名稱,并與當前 Bean 的名稱進行比較
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
// 如果切面名稱與 Bean 名稱相等,則表示應該跳過對該 Bean 的處理
return true;
}
}
}
// 如果沒有匹配到需要跳過的情況,則調用父類的 shouldSkip 方法進行判斷
return super.shouldSkip(beanClass, beanName);
}

在shouldSkip()中首先獲得四個增強器即切面中的四個通知方法,將通知方法包裝為InstantiationModelAwarePointcutAdvisor類型的,
判斷增強器是否是AspectJPointcutAdvisor類型的,而我們的類型不是,就會調用父類的super.shouldSkip(beanClass, beanName);
返回false,最后就返回null,繼續 doCreateBean(beanName, mbdToUse, args)-->createBeanInstance(beanName, mbd, args)
-->populateBean(beanName, mbd, instanceWrapper)-->initializeBean(beanName, exposedObject, mbd)-->applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
之后又來到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(Object, String)方法

調用 wrapIfNecessary(bean, beanName, cacheKey) 進入其中
/**
* 如果有必要,對指定的 Bean 進行包裝(創建代理)。
*
* @param bean 要檢查并可能包裝的 Bean 實例
* @param beanName Bean 的名稱
* @param cacheKey 用于緩存的鍵,代表當前 Bean 的唯一標識
* @return 如果需要,返回包裝后的代理對象;否則返回原始的 Bean 實例
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 檢查 beanName 是否不為空,并且 targetSourcedBeans 集合中包含該 beanName
// 如果是,則表示該 Bean 已經由 TargetSource 處理過,不需要再進行包裝,直接返回原始 Bean
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 從 advisedBeans 緩存中獲取當前 Bean 對應的處理標記
// 如果標記為 false,表示該 Bean 不需要被代理,直接返回原始 Bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 檢查該 Bean 的類是否為基礎設施類(如 Spring 內部使用的類),或者是否應該跳過該 Bean 的處理
// 如果是,則將該 Bean 的處理標記為 false 并放入 advisedBeans 緩存中,然后返回原始 Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果存在通知(Advice),則創建代理
// 獲取該 Bean 對應的通知和通知器數組
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果獲取到的通知和通知器數組不為 DO_NOT_PROXY(表示需要進行代理)
if (specificInterceptors != DO_NOT_PROXY) {
// 將該 Bean 的處理標記為 true 并放入 advisedBeans 緩存中
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 創建代理對象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 將代理對象的類型放入 proxyTypes 緩存中
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理對象
return proxy;
}
// 如果不需要進行代理,將該 Bean 的處理標記為 false 并放入 advisedBeans 緩存中
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// 返回原始 Bean
return bean;
}
獲取所有候選增強器,然后通過切點表達式進行篩選,獲得與其當前匹配的bean增強器(通知方法),如何獲取呢?


通過 createProxy() 創建代理對象,最后保存當前bean到 advisedBeans中,表示當前bean已經增強

先根據 Bean 名稱獲取其對應的增強器(通知方法),保存到proxyFactory中,通過proxyFactory.getProxy(getProxyClassLoader()),獲得代理對象
/**
* 創建指定 Bean 的代理對象。
*
* @param beanClass Bean 的類對象,即要被代理的目標類
* @param beanName Bean 的名稱,用于標識該 Bean
* @param specificInterceptors 該 Bean 對應的特定攔截器和通知器數組
* @param targetSource 目標對象的源,用于獲取實際的目標對象
* @return 創建好的代理對象
*/
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
// 檢查當前的 Bean 工廠是否為 ConfigurableListableBeanFactory 類型
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
// 如果是,則通過 AutoProxyUtils 工具類暴露目標類信息到 Bean 工廠中
// 這有助于在某些情況下讓其他組件知道目標類的實際類型
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 創建一個 ProxyFactory 實例,用于創建代理對象
ProxyFactory proxyFactory = new ProxyFactory();
// 將當前對象的配置信息復制到 ProxyFactory 中
// 確保代理工廠使用相同的配置
proxyFactory.copyFrom(this);
// 檢查 ProxyFactory 是否已經配置為代理目標類(使用 CGLIB 代理)
if (!proxyFactory.isProxyTargetClass()) {
// 如果沒有配置為代理目標類,則檢查是否應該代理目標類
if (shouldProxyTargetClass(beanClass, beanName)) {
// 如果應該代理目標類,則將 ProxyFactory 的配置設置為代理目標類
proxyFactory.setProxyTargetClass(true);
} else {
// 否則,評估目標類實現的接口,根據接口情況來配置代理方式
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 根據 Bean 名稱獲取其對應的增強器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 將構建好的增強器添加到 ProxyFactory 中
proxyFactory.addAdvisors(advisors);
// 設置目標對象(被代理對象)
proxyFactory.setTargetSource(targetSource);
// 對 ProxyFactory 進行自定義配置,允許子類進行額外的定制
customizeProxyFactory(proxyFactory);
// 設置 ProxyFactory 是否凍結代理配置
// 如果凍結,則在創建代理后不能再修改代理的配置
proxyFactory.setFrozen(this.freezeProxy);
// 檢查通知器是否已經預先過濾
if (advisorsPreFiltered()) {
// 如果已經預先過濾,則設置 ProxyFactory 為預過濾狀態
proxyFactory.setPreFiltered(true);
}
// 使用 ProxyFactory 創建代理對象,并指定代理類加載器
return proxyFactory.getProxy(getProxyClassLoader());
}
進入其中
/**
* 根據提供的 AOP 配置信息創建 AOP 代理對象。
*
* @param config 包含 AOP 代理配置的 AdvisedSupport 對象
* @return 一個 AopProxy 實例,用于生成具體的 AOP 代理對象
* @throws AopConfigException 如果配置信息不符合代理創建要求,拋出此異常
*/
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 檢查是否滿足使用 CGLIB 代理的條件:
// 1. 是否開啟了優化選項
// 2. 是否明確指定使用目標類代理
// 3. 是否沒有用戶提供的代理接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 獲取目標類的 Class 對象
Class<?> targetClass = config.getTargetClass();
// 如果目標類為 null,說明無法確定目標類,拋出 AopConfigException 異常
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果目標類是接口或者是代理類,使用 JDK 動態代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否則,使用 ObjenesisCglibAopProxy(基于 CGLIB 的代理)
return new ObjenesisCglibAopProxy(config);
} else {
// 如果不滿足使用 CGLIB 代理的條件,默認使用 JDK 動態代理
return new JdkDynamicAopProxy(config);
}
}
spring自動決定使用JDK方式代理還是使用Cglib方式代理

至此就創建出代理對象啦,并返回回去了,以后容器中拿到的就是代理對象了,接下來拿到代理對象,如何調用增強方法

浙公網安備 33010602011771號