轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80725173
我們在這篇文章中來分析一下AnnotationAwareAspectJAutoProxyCreator這個類,看這個類的名字我們大概可以知道它主要是爲AspectJ註解提供服務的類。這個類不得了了是一個相當厲害的類,在這個類中可以識別應用中的所有切面類,爲目標類找尋合適的Advisor,將目標類變爲代理類等功能。話不多說了,下面我們來簡單的分析一下這個類。
首先我們來看一下這個類的類圖:
從上面的圖中我們可以看到AnnotationAwareAspectJAutoProxyCreator這個類間接實現了BeanFactoryAware、BeanClassLoaderAware、Ordered、BeanPostProcessor接口。如果之前沒有了解過Spring Bean的生命週期(或者是Spring開放的對Bean進行修改的擴展接口)的話,請點擊這裏查看(Spring Bean的生命週期小析(一) 和 Spring Bean的生命週期小析(二))這裏就不再多說了。上面提到的接口的實現類大多是在AbstractAutoProxyCreator這個類中實現的。Spring提供的這些關於Bean的擴展接口大大方便了我們在Bean的創建過程中對Bean進行一些修改的操作。我們按照順序來看看AnnotationAwareAspectJAutoProxyCreator這個關係鏈上對這些接口的實現。
AbstractAdvisorAutoProxyCreator#setBeanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory) {
//掉用父類的setBeanFactory 這裏只是一個簡單的賦值
super.setBeanFactory(beanFactory);
//如果BeanFactory不是ConfigurableListableBeanFactory類型的 拋出異常
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
//初始化BeanFactory
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
//這個方法在AnnotationAwareAspectJAutoProxyCreator這個類型中
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//調用父類的initBeanFactory 執行的內容如下:
//this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
//創建BeanFactoryAdvisorRetrievalHelperAdapter 從BeanFactory中獲取Advisor類型的Bean
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
//創建ReflectiveAspectJAdvisorFactory 相當重要的一個類
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
//創建BeanFactoryAspectJAdvisorsBuilderAdapter 相當重要的一個類
//爲目標類型創建對應的Advisor的類
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
AbstractAutoProxyCreator#postProcessBeforeInstantiation
這個方法可以讓我們在Bean被Spring容器實例化之前提前創建Bean,如果這個方法返回的值不是null,那就中斷其他類對這個接口的實現,直接返回這個創建的Bean。在AbstractAutoProxyCreator中其源碼如下:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
//得到一個緩存的key 實現是:如果是beanClass是FactoryBean類型,則在beanName前面加&
Object cacheKey = getCacheKey(beanClass, beanName);
//如果目標Bean的集合中包這個beanName的話 則跳過
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//isInfrastructureClass 判斷是不是負責AOP基礎建設的Bean,如果是AOP基礎建設的Bean不能在這裏被創建代理對象
//那麼什麼樣的Bean是AOP的基礎建設Bean呢?Advice、Pointcut、Advisor、AopInfrastructureBean類型的Bean
//以及含有Aspect註解的Bean
//shouldSkip這個方法是判斷這個類型的Bean能不能被跳過,如果可以跳過,那麼就不提前創建這個類
//這個類我們在下面詳細分析
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
//緩存這個beanClass
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.
if (beanName != null) {
//一般我們都是不配置TargetSourceCreator 下面的步驟我們先跳過 在後面我們還會繼續分析下面的內容的
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
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;
}
}
AspectJAwareAdvisorAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
//我們重點看到是findCandidateAdvisors這個方法的內容
//查找所有可選擇對的Advisor 並且或進行緩存
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
//如果AbstractAspectJAdvice類型的Advice中有aspectName和beanName相等則跳過
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
//父類直接返回一個false
return super.shouldSkip(beanClass, beanName);
}
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 同樣是先調用父類的findCandidateAdvisors
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
//構建所有切面Bean中的Advisor
//很重要的一個方法 下面分析
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
// AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
//這個advisorRetrievalHelper 就是我們在 initBeanFactory中創建的BeanFactoryAdvisorRetrievalHelper
return this.advisorRetrievalHelper.findAdvisorBeans();
}
// BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
//這個方法的內容是從Spring容器中獲取Advisor類型的Bean
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
//先看看之前是不是緩存過
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!
//上面的註釋說的很清楚 這裏不會初始化FactoryBean 爲什麼會這樣說呢?因爲提前導致FactoryBean類型的Bean被創建的話是會有問題的
//從BeanFactory中獲取所有的Advisor類型的Bean
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
//這裏進行賦值緩存
this.cachedAdvisorBeanNames = advisorNames;
}
}
//如果沒有Advisor類型的Bean的話 直接返回
//如果你有特殊需求的話 可以實現Advisor接口,並向Spring容器中注入對應的Bean
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
//這裏是默認創建了一個 Advisor類型的集合
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
//這裏默認返回的是true
if (isEligibleBean(name)) {
//如果是正在創建中的Bean 則跳過
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
//從BeanFactory中獲取對應的Bean 這裏如果Bean還沒創建 會導致Bean創建
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
//異常處理 略
}
}
}
}
return advisors;
}
下面我們來看看BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors中的這個方法,從名字我們就可以看出來這是一個從BeanFactory中構建Advisor的方法。
public List<Advisor> buildAspectJAdvisors() {
//所有的切面的名字 這裏的處理邏輯和上面的是一樣的 獲取到所有的切面BeanName之後緩存起來 volatile類型的
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
//這裏又賦值了一次 看着這個邏輯是不是和某個單例的寫法很像啊?
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
//這裏是從BeanFactory中獲取所有的Bean
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
//這裏默認都是true
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.
//注意看上面這個註釋的內容:在這個場景下我們獲取BeanClass的時候必須要小心處理,以免會提前初始化
//Bean,這些Bean在初始化之後會被Spring容器緩存起來,但是這些Bean可能還沒有被織入。
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//判斷上面獲取到的BeanClass是否帶有Aspect註解
if (this.advisorFactory.isAspect(beanType)) {
//添加到 aspectNames中
aspectNames.add(beanName);
//創建切面元數據 這部門的內容和我們之前分析大致差不多 我們就不再詳細分析了
//請看這裏: https://blog.csdn.net/zknxx/article/details/79685290
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
//注意這裏放入了 BeanFactory的引用 方便後面從BeanFactory中獲取切面的實例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
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 {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
//這裏使用的是 PrototypeAspectInstanceFactory
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
//下面這些就是從緩存中獲取Advisor了
List<Advisor> advisors = new LinkedList<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);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
總結起來findCandidateAdvisors這個方法的內容就是從Spring容器中獲取所有Advisor類型的Bean和切面中所有帶有通知註解的方法並將其封裝爲Advisor。那麼其實我們在AbstractAutoProxyCreator的postProcessBeforeInstantiation方法中就獲取到了Spring容器中的所有Advisor。
AbstractAutoProxyCreator#postProcessAfterInstantiation
//通常都是返回true
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
AbstractAutoProxyCreator#postProcessPropertyValues
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
//不做處理
return pvs;
}
AbstractAutoProxyCreator#postProcessBeforeInitialization
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
//不做處理原樣返回
return bean;
}
AbstractAutoProxyCreator#postProcessAfterInitialization
這個方法需要重點分析一下了
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
//獲取緩存的key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//如果不是提前引用的Bean
if (!this.earlyProxyReferences.contains(cacheKey)) {
//如果需要的話 對傳入的Bean進行包裝
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
//這個方法的主要作用就是創建代理對象
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果已經創建過了
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//如果這裏返回的是False的話 直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//這裏又判斷了一次不再多說了、、、
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//getAdvicesAndAdvisorsForBean這個方法下面我們要重點說一下
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//創建代理對象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//如果不需要創建代理對象的話 這裏緩存false
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80725173