/* * 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; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.aopalliance.intercept.Interceptor; import org.aopalliance.intercept.MethodInterceptor; import org.springframework.aop.Advisor; import org.springframework.aop.IntroductionAdvisor; import org.springframework.aop.MethodMatcher; import org.springframework.aop.PointcutAdvisor; import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry; import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry; import org.springframework.aop.support.MethodMatchers; /** * A simple but definitive way of working out an advice chain for a Method, * given an {@link Advised} object. Always rebuilds each advice chain; * caching can be provided by subclasses. * * @author Juergen Hoeller * @author Rod Johnson * @author Adrian Colyer * @since 2.0.3 */ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable { public List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class targetClass) { // This is somewhat tricky... we have to process introductions first, // but we need to preserve order in the ultimate list. List interceptorList = new ArrayList(config.getAdvisors().length); boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); for (int i = 0; i < advisors.length; i++) { Advisor advisor = advisors[i]; if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (int j = 0; j < interceptors.length; j++) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j], mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; } /** * Determine whether the Advisors contain matching introductions. */ private static boolean hasMatchingIntroductions(Advised config, Class targetClass) { for (int i = 0; i < config.getAdvisors().length; i++) { Advisor advisor = config.getAdvisors()[i]; if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (ia.getClassFilter().matches(targetClass)) { return true; } } } return false; } }