版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/86475696
概述
BeanFactoryAdvisorRetrievalHelper
是一个Spring AOP
内部工具类,该工具类用来从bean
容器,也就是BeanFactory
中获取所有Spring
顾问Advisor
bean
。
这里的
Spring
Advisor
bean
指的是实现了接口org.springframework.aop.Advisor
的bean
。
该类具体的使用可以参考AbstractAdvisorAutoProxyCreator
。
源代码解析
package org.springframework.aop.framework.autoproxy;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.Advisor;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
public class BeanFactoryAdvisorRetrievalHelper {
private static final Log logger = LogFactory.getLog(BeanFactoryAdvisorRetrievalHelper.class);
private final ConfigurableListableBeanFactory beanFactory;
@Nullable
private volatile String[] cachedAdvisorBeanNames;
/**
* Create a new BeanFactoryAdvisorRetrievalHelper for the given BeanFactory.
* @param beanFactory the ListableBeanFactory to scan
*/
public BeanFactoryAdvisorRetrievalHelper(ConfigurableListableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
this.beanFactory = beanFactory;
}
/**
* Find all eligible Advisor beans in the current bean factory,
* ignoring FactoryBeans and excluding beans that are currently in creation.
* 找到当前bean容器中所有符合条件的Advisor顾问bean并返回,但是忽略FactoryBeans
* 和那些正在创建中的bean
* @return the list of org.springframework.aop.Advisor beans
* @see #isEligibleBean
*/
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!
// 获取bean容器及其父容器中所有Spring Advisor bean的名称
// includeNonSingletons:true=>也包含 prototype,scoped bean,不光是 singleton bean
// allowEagerInit:false=>不要初始化lazy-init 单例 bean和通过FactoryBean创建的bean
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 将获取到的Advisor bean 的名称记录到 this.cachedAdvisorBeanNames
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
// 容器中不存在Spring Advisor bean,返回空List
return new ArrayList<>();
}
// 准备一个Advisor List advisors ,用于保存和返回真正符合条件的Advisor
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
// 针对上面从容器中获取到的所有Advisor bean, 检查它们是否符合条件,
// 这里检查符合条件的逻辑由谓词isEligibleBean()完成
// isEligibleBean() 在本类中的缺省实现是:总是返回true,
// 实际上该类可以被继承,然后重写isEligibleBean()方法实现自己的
// 符合条件检查逻辑
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
// 忽略正在创建中的bean
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
// 遇到了一个真正符合条件的bean,将其实例化,然后放到 advisors 中,
// 如果创建过程中遇到异常是因为其依赖bean正在创建中,则先忽略该bean,
// 如果是其他异常,抛出异常,中断当前方法
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;
}
/**
* Determine whether the aspect bean with the given name is eligible.
* The default implementation always returns true.
* @param beanName the name of the aspect bean
* @return whether the bean is eligible
*/
protected boolean isEligibleBean(String beanName) {
return true;
}
}