001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.aop.framework.autoproxy;
018:
019: import java.util.LinkedList;
020: import java.util.List;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024:
025: import org.springframework.aop.Advisor;
026: import org.springframework.beans.factory.BeanCreationException;
027: import org.springframework.beans.factory.BeanCurrentlyInCreationException;
028: import org.springframework.beans.factory.BeanFactoryUtils;
029: import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
030: import org.springframework.util.Assert;
031:
032: /**
033: * Helper for retrieving standard Spring Advisors from a BeanFactory,
034: * for use with auto-proxying.
035: *
036: * @author Juergen Hoeller
037: * @since 2.0.2
038: * @see AbstractAdvisorAutoProxyCreator
039: */
040: public class BeanFactoryAdvisorRetrievalHelper {
041:
042: private static final Log logger = LogFactory
043: .getLog(BeanFactoryAdvisorRetrievalHelper.class);
044:
045: private final ConfigurableListableBeanFactory beanFactory;
046:
047: private String[] cachedAdvisorBeanNames;
048:
049: /**
050: * Create a new BeanFactoryAdvisorRetrievalHelper for the given BeanFactory.
051: * @param beanFactory the ListableBeanFactory to scan
052: */
053: public BeanFactoryAdvisorRetrievalHelper(
054: ConfigurableListableBeanFactory beanFactory) {
055: Assert.notNull(beanFactory,
056: "ListableBeanFactory must not be null");
057: this .beanFactory = beanFactory;
058: }
059:
060: /**
061: * Find all eligible Advisor beans in the current bean factory,
062: * ignoring FactoryBeans and excluding beans that are currently in creation.
063: * @return the list of {@link org.springframework.aop.Advisor} beans
064: * @see #isEligibleBean
065: */
066: public List findAdvisorBeans() {
067: // Determine list of advisor bean names, if not cached already.
068: String[] advisorNames = null;
069: synchronized (this ) {
070: advisorNames = this .cachedAdvisorBeanNames;
071: if (advisorNames == null) {
072: // Do not initialize FactoryBeans here: We need to leave all regular beans
073: // uninitialized to let the auto-proxy creator apply to them!
074: advisorNames = BeanFactoryUtils
075: .beanNamesForTypeIncludingAncestors(
076: this .beanFactory, Advisor.class, true,
077: false);
078: this .cachedAdvisorBeanNames = advisorNames;
079: }
080: }
081: if (advisorNames.length == 0) {
082: return new LinkedList();
083: }
084:
085: List advisors = new LinkedList();
086: for (int i = 0; i < advisorNames.length; i++) {
087: String name = advisorNames[i];
088: if (isEligibleBean(name)
089: && !this .beanFactory.isCurrentlyInCreation(name)) {
090: try {
091: advisors.add(this .beanFactory.getBean(name));
092: } catch (BeanCreationException ex) {
093: Throwable rootCause = ex.getMostSpecificCause();
094: if (rootCause instanceof BeanCurrentlyInCreationException) {
095: BeanCreationException bce = (BeanCreationException) rootCause;
096: if (this .beanFactory.isCurrentlyInCreation(bce
097: .getBeanName())) {
098: if (logger.isDebugEnabled()) {
099: logger
100: .debug("Ignoring currently created advisor '"
101: + name
102: + "': "
103: + ex.getMessage());
104: }
105: // Ignore: indicates a reference back to the bean we're trying to advise.
106: // We want to find advisors other than the currently created bean itself.
107: continue;
108: }
109: }
110: throw ex;
111: }
112: }
113: }
114: return advisors;
115: }
116:
117: /**
118: * Determine whether the aspect bean with the given name is eligible.
119: * <p>The default implementation always returns <code>true</code>.
120: * @param beanName the name of the aspect bean
121: * @return whether the bean is eligible
122: */
123: protected boolean isEligibleBean(String beanName) {
124: return true;
125: }
126:
127: }
|