/* * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.aop.framework.autoproxy; import java.util.LinkedList; 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.util.Assert; /** * 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; private 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 {@link org.springframework.aop.Advisor} beans * @see #isEligibleBean */ public List 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! advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList(); } List advisors = new LinkedList(); for (int i = 0; i < advisorNames.length; i++) { String name = advisorNames[i]; if (isEligibleBean(name) && !this.beanFactory.isCurrentlyInCreation(name)) { try { advisors.add(this.beanFactory.getBean(name)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Ignoring currently created advisor '" + name + "': " + 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. * <p>The default implementation always returns <code>true</code>. * @param beanName the name of the aspect bean * @return whether the bean is eligible */ protected boolean isEligibleBean(String beanName) { return true; } }