概述
BeanFactoryAdvisorRetrievalHelper
是Spring AOP
框架提供的一个工具类,从整个IoC
容器范围获取所有的Spring Advisor bean
组件,用于辅助自动代理机制。
该工具类的核心逻辑在于其方法List<Advisor> findAdvisorBeans()
,该方法从容器(包含祖先容器)中找到并返回所有类型为org.springframework.aop.Advisor
且创建完成的bean
。Advisor bean
实例获取过程中如果遇到BeanCreationException
异常则忽略相应的Advisor bean
继续处理其他的Advisor bean
,而如果是其他异常,则终止处理继续抛出异常。
BeanFactoryAdvisorRetrievalHelper
的使用如下 :
- 被继承
// AbstractAdvisorAutoProxyCreator 类代码片段
// AbstractAdvisorAutoProxyCreator 的一个嵌套子类, 扩展定制了 isEligibleBean 方法
private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {
public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
super(beanFactory);
}
@Override
protected boolean isEligibleBean(String beanName) {
return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
}
}
- 被使用
// AbstractAdvisorAutoProxyCreator 类代码片段
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
@Nullable
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
// ...
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
// ...
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
// ...
}
源代码
源代码版本 : spring-aop-5.1.5.RELEASE
package org.springframework.aop.framework.autoproxy;
// 省略 import 行
/**
* Helper for retrieving standard Spring Advisors from a BeanFactory,
* for use with auto-proxying.
*
* @author Juergen Hoeller
* @since 2.0.2
* @see AbstractAdvisorAutoProxyCreator
*/
public class BeanFactoryAdvisorRetrievalHelper {
private static final Log logger = LogFactory.getLog(BeanFactoryAdvisorRetrievalHelper.class);
private final ConfigurableListableBeanFactory beanFactory;
// 缓存机制
// 当前工具类的方法 findAdvisorBeans 可能被调用多次,首次调用时会发现所有的符合条件的 bean 的名称,
// 这些名称会缓存在这里供后续调用直接使用而不是再次从容器获取
@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.
* @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.
// 先尝试从缓存中获取容器中所有 Advisor bean 的名称
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!
// 如果缓存为空,尝试从容器以及其父容器分析得到所有 Advisor bean 的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 缓存找到的 Advisor bean 的名称
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
// 容器中不存在 Advisor bean 的情况
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
// 从 bean 名称得到 bean 实例对象
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
// 创建中的 bean 被忽略
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
// 获取 Advisor bean 实例过程中如果遇到 BeanCreationException 异常则跳过该 bean , 继续;
// 如果是其他异常,则继续抛出异常
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;
}
}