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.Collections;
020: import java.util.List;
021:
022: import org.springframework.aop.TargetSource;
023: import org.springframework.aop.support.AopUtils;
024: import org.springframework.beans.factory.BeanFactory;
025: import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
026: import org.springframework.core.OrderComparator;
027:
028: /**
029: * Generic auto proxy creator that builds AOP proxies for specific beans
030: * based on detected Advisors for each bean.
031: *
032: * <p>Subclasses must implement the abstract {@link #findCandidateAdvisors()}
033: * method to return a list of Advisors applying to any object. Subclasses can
034: * also override the inherited {@link #shouldSkip} method to exclude certain
035: * objects from auto-proxying.
036: *
037: * <p>Advisors or advices requiring ordering should implement the
038: * {@link org.springframework.core.Ordered} interface. This class sorts
039: * Advisors by Ordered order value. Advisors that don't implement the
040: * Ordered interface will be considered as unordered; they will appear
041: * at the end of the advisor chain in undefined order.
042: *
043: * @author Rod Johnson
044: * @author Juergen Hoeller
045: * @see #findCandidateAdvisors
046: */
047: public abstract class AbstractAdvisorAutoProxyCreator extends
048: AbstractAutoProxyCreator {
049:
050: private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
051:
052: public void setBeanFactory(BeanFactory beanFactory) {
053: super .setBeanFactory(beanFactory);
054: if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
055: throw new IllegalStateException(
056: "Cannot use AdvisorAutoProxyCreator without a ConfigurableListableBeanFactory");
057: }
058: initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
059: }
060:
061: protected void initBeanFactory(
062: ConfigurableListableBeanFactory beanFactory) {
063: this .advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(
064: beanFactory);
065: }
066:
067: protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass,
068: String name, TargetSource targetSource) {
069: List advisors = findEligibleAdvisors(beanClass);
070: if (advisors.isEmpty()) {
071: return DO_NOT_PROXY;
072: }
073: return advisors.toArray();
074: }
075:
076: /**
077: * Find all eligible advices for auto-proxying this class.
078: * @param clazz the clazz to find advisors for
079: * @return the empty list, not <code>null</code>,
080: * if there are no pointcuts or interceptors
081: * @see #findCandidateAdvisors
082: * @see #sortAdvisors
083: * @see #extendAdvisors
084: */
085: protected List findEligibleAdvisors(Class clazz) {
086: List eligibleAdvisors = AopUtils.findAdvisorsThatCanApply(
087: findCandidateAdvisors(), clazz);
088: if (!eligibleAdvisors.isEmpty()) {
089: eligibleAdvisors = sortAdvisors(eligibleAdvisors);
090: }
091: extendAdvisors(eligibleAdvisors);
092: return eligibleAdvisors;
093: }
094:
095: /**
096: * Find all candidate advisors to use in auto-proxying.
097: * @return list of candidate Advisors
098: */
099: protected List findCandidateAdvisors() {
100: return this .advisorRetrievalHelper.findAdvisorBeans();
101: }
102:
103: /**
104: * Return whether the Advisor bean with the given name is eligible
105: * for proxying in the first place.
106: * @param beanName the name of the Advisor bean
107: * @return whether the bean is eligible
108: */
109: protected boolean isEligibleAdvisorBean(String beanName) {
110: return true;
111: }
112:
113: /**
114: * Sort advisors based on ordering. Subclasses may choose to override this
115: * method to customize the sorting strategy.
116: * @param advisors the source List of Advisors
117: * @return the sorted List of Advisors
118: * @see org.springframework.core.Ordered
119: * @see org.springframework.core.OrderComparator
120: */
121: protected List sortAdvisors(List advisors) {
122: Collections.sort(advisors, new OrderComparator());
123: return advisors;
124: }
125:
126: /**
127: * Extension hook that subclasses can override to register additional Advisors,
128: * given the sorted Advisors obtained to date.
129: * <p>The default implementation is empty.
130: * <p>Typically used to add Advisors that expose contextual information
131: * required by some of the later advisors.
132: * @param candidateAdvisors Advisors that have already been identified as
133: * applying to a given bean
134: */
135: protected void extendAdvisors(List candidateAdvisors) {
136: }
137:
138: /**
139: * Subclass of BeanFactoryAdvisorRetrievalHelper that delegates to
140: * surrounding AbstractAdvisorAutoProxyCreator facilities.
141: */
142: private class BeanFactoryAdvisorRetrievalHelperAdapter extends
143: BeanFactoryAdvisorRetrievalHelper {
144:
145: public BeanFactoryAdvisorRetrievalHelperAdapter(
146: ConfigurableListableBeanFactory beanFactory) {
147: super (beanFactory);
148: }
149:
150: protected boolean isEligibleBean(String beanName) {
151: return AbstractAdvisorAutoProxyCreator.this
152: .isEligibleAdvisorBean(beanName);
153: }
154: }
155:
156: }
|