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;
018:
019: import java.io.Serializable;
020: import java.lang.reflect.Method;
021: import java.util.ArrayList;
022: import java.util.Arrays;
023: import java.util.List;
024:
025: import org.aopalliance.intercept.Interceptor;
026: import org.aopalliance.intercept.MethodInterceptor;
027:
028: import org.springframework.aop.Advisor;
029: import org.springframework.aop.IntroductionAdvisor;
030: import org.springframework.aop.MethodMatcher;
031: import org.springframework.aop.PointcutAdvisor;
032: import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry;
033: import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
034: import org.springframework.aop.support.MethodMatchers;
035:
036: /**
037: * A simple but definitive way of working out an advice chain for a Method,
038: * given an {@link Advised} object. Always rebuilds each advice chain;
039: * caching can be provided by subclasses.
040: *
041: * @author Juergen Hoeller
042: * @author Rod Johnson
043: * @author Adrian Colyer
044: * @since 2.0.3
045: */
046: public class DefaultAdvisorChainFactory implements AdvisorChainFactory,
047: Serializable {
048:
049: public List getInterceptorsAndDynamicInterceptionAdvice(
050: Advised config, Method method, Class targetClass) {
051: // This is somewhat tricky... we have to process introductions first,
052: // but we need to preserve order in the ultimate list.
053: List interceptorList = new ArrayList(
054: config.getAdvisors().length);
055: boolean hasIntroductions = hasMatchingIntroductions(config,
056: targetClass);
057: AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry
058: .getInstance();
059: Advisor[] advisors = config.getAdvisors();
060: for (int i = 0; i < advisors.length; i++) {
061: Advisor advisor = advisors[i];
062: if (advisor instanceof PointcutAdvisor) {
063: // Add it conditionally.
064: PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
065: if (config.isPreFiltered()
066: || pointcutAdvisor.getPointcut()
067: .getClassFilter().matches(targetClass)) {
068: MethodInterceptor[] interceptors = registry
069: .getInterceptors(advisor);
070: MethodMatcher mm = pointcutAdvisor.getPointcut()
071: .getMethodMatcher();
072: if (MethodMatchers.matches(mm, method, targetClass,
073: hasIntroductions)) {
074: if (mm.isRuntime()) {
075: // Creating a new object instance in the getInterceptors() method
076: // isn't a problem as we normally cache created chains.
077: for (int j = 0; j < interceptors.length; j++) {
078: interceptorList
079: .add(new InterceptorAndDynamicMethodMatcher(
080: interceptors[j], mm));
081: }
082: } else {
083: interceptorList.addAll(Arrays
084: .asList(interceptors));
085: }
086: }
087: }
088: } else if (advisor instanceof IntroductionAdvisor) {
089: IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
090: if (config.isPreFiltered()
091: || ia.getClassFilter().matches(targetClass)) {
092: Interceptor[] interceptors = registry
093: .getInterceptors(advisor);
094: interceptorList.addAll(Arrays.asList(interceptors));
095: }
096: } else {
097: Interceptor[] interceptors = registry
098: .getInterceptors(advisor);
099: interceptorList.addAll(Arrays.asList(interceptors));
100: }
101: }
102: return interceptorList;
103: }
104:
105: /**
106: * Determine whether the Advisors contain matching introductions.
107: */
108: private static boolean hasMatchingIntroductions(Advised config,
109: Class targetClass) {
110: for (int i = 0; i < config.getAdvisors().length; i++) {
111: Advisor advisor = config.getAdvisors()[i];
112: if (advisor instanceof IntroductionAdvisor) {
113: IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
114: if (ia.getClassFilter().matches(targetClass)) {
115: return true;
116: }
117: }
118: }
119: return false;
120: }
121:
122: }
|