Save This Page
Home » Spring-Framework-090522 » org.springframework » aop » aspectj » autoproxy » [javadoc | source]
    1   /*
    2    * Copyright 2002-2007 the original author or authors.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.springframework.aop.aspectj.autoproxy;
   18   
   19   import java.util.Comparator;
   20   import java.util.Iterator;
   21   import java.util.LinkedList;
   22   import java.util.List;
   23   
   24   import org.aopalliance.aop.Advice;
   25   import org.aspectj.util.PartialOrder;
   26   import org.aspectj.util.PartialOrder.PartialComparable;
   27   
   28   import org.springframework.aop.Advisor;
   29   import org.springframework.aop.aspectj.AbstractAspectJAdvice;
   30   import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
   31   import org.springframework.aop.aspectj.AspectJProxyUtils;
   32   import org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator;
   33   import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
   34   import org.springframework.core.Ordered;
   35   import org.springframework.util.ClassUtils;
   36   
   37   /**
   38    * {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}
   39    * subclass that exposes AspectJ's invocation context and understands AspectJ's rules
   40    * for advice precedence when multiple pieces of advice come from the same aspect.
   41    *
   42    * @author Adrian Colyer
   43    * @author Juergen Hoeller
   44    * @author Ramnivas Laddad
   45    * @since 2.0
   46    */
   47   public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
   48   
   49   	private static final Comparator DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
   50   
   51   
   52   	/**
   53   	 * Sort the rest by AspectJ precedence. If two pieces of advice have
   54   	 * come from the same aspect they will have the same order.
   55   	 * Advice from the same aspect is then further ordered according to the
   56   	 * following rules:
   57   	 * <ul>
   58   	 * <li>if either of the pair is after advice, then the advice declared
   59   	 * last gets highest precedence (runs last)</li>
   60   	 * <li>otherwise the advice declared first gets highest precedence (runs first)</li>
   61   	 * </ul>
   62   	 * <p><b>Important:</b> Advisors are sorted in precedence order, from highest
   63   	 * precedence to lowest. "On the way in" to a join point, the highest precedence
   64   	 * advisor should run first. "On the way out" of a join point, the highest precedence
   65   	 * advisor should run last.
   66   	 */
   67   	protected List sortAdvisors(List advisors) {
   68   		// build list for sorting
   69   		List partiallyComparableAdvisors = new LinkedList();
   70   		for (Iterator it = advisors.iterator(); it.hasNext();) {
   71   			Advisor element = (Advisor) it.next();
   72   			PartiallyComparableAdvisorHolder advisor =
   73   					new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR);
   74   			partiallyComparableAdvisors.add(advisor);
   75   		}		
   76   		
   77   		// sort it
   78   		List sorted = PartialOrder.sort(partiallyComparableAdvisors);
   79   		if (sorted == null) {
   80   			// TODO: work much harder to give a better error message here.
   81   			throw new IllegalArgumentException("Advice precedence circularity error");
   82   		}
   83   		
   84   		// extract results again
   85   		List result = new LinkedList();
   86   		for (Iterator it = sorted.iterator(); it.hasNext();) {
   87   			PartiallyComparableAdvisorHolder pcAdvisor = (PartiallyComparableAdvisorHolder) it.next();
   88   			result.add(pcAdvisor.getAdvisor());
   89   		}
   90   		
   91   		return result;
   92   	}
   93   
   94   	/**
   95   	 * Adds an {@link ExposeInvocationInterceptor} to the beginning of the advice chain.
   96   	 * These additional advices are needed when using AspectJ expression pointcuts
   97   	 * and when using AspectJ-style advice.
   98   	 */
   99   	protected void extendAdvisors(List candidateAdvisors) {
  100   		AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
  101   	}
  102   
  103   	protected boolean shouldSkip(Class beanClass, String beanName) {
  104   		// TODO: Consider optimization by caching the list of the aspect names
  105   		List candidtate = findCandidateAdvisors();
  106   		for (Iterator it = candidtate.iterator(); it.hasNext();) {
  107   			Advisor advisor = (Advisor) it.next();
  108   			if (advisor instanceof AspectJPointcutAdvisor) {
  109   				if(((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
  110   					return true;
  111   				}
  112   			}
  113   		}
  114   		return super.shouldSkip(beanClass, beanName);
  115   	}
  116   
  117   	/**
  118   	 * Implements AspectJ PartialComparable interface for defining partial orderings.
  119   	 */
  120   	private static class PartiallyComparableAdvisorHolder implements PartialComparable {
  121   
  122   		private final Advisor advisor;
  123   
  124   		private final Comparator comparator;
  125   
  126   		public PartiallyComparableAdvisorHolder(Advisor advisor, Comparator comparator) {
  127   			this.advisor = advisor;
  128   			this.comparator = comparator;
  129   		}
  130   
  131   		public int compareTo(Object obj) {
  132   			Advisor otherAdvisor = ((PartiallyComparableAdvisorHolder) obj).advisor;
  133   			return this.comparator.compare(this.advisor, otherAdvisor);
  134   		}
  135   
  136   		public int fallbackCompareTo(Object obj) {
  137   			return 0;
  138   		}
  139   
  140   		public Advisor getAdvisor() {
  141   			return this.advisor;
  142   		}
  143   
  144   		public String toString() {
  145   			StringBuffer sb = new StringBuffer();
  146   			Advice advice = this.advisor.getAdvice();
  147   			sb.append(ClassUtils.getShortName(advice.getClass()));
  148   			sb.append(": ");
  149   			if (this.advisor instanceof Ordered) {
  150   				sb.append("order " + ((Ordered) this.advisor).getOrder() + ", ");
  151   			}
  152   			if (advice instanceof AbstractAspectJAdvice) {
  153   				AbstractAspectJAdvice ajAdvice = (AbstractAspectJAdvice) advice;
  154   				sb.append(ajAdvice.getAspectName());
  155   				sb.append(", declaration order ");
  156   				sb.append(ajAdvice.getDeclarationOrder());
  157   			}
  158   			return sb.toString();
  159   		}
  160   	}
  161   
  162   }

Save This Page
Home » Spring-Framework-090522 » org.springframework » aop » aspectj » autoproxy » [javadoc | source]