All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2020 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
 *
 *      https://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.aspectj.autoproxy;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import org.aopalliance.aop.Advice;
import org.aspectj.util.PartialOrder;
import org.aspectj.util.PartialOrder.PartialComparable;

import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
import org.springframework.aop.aspectj.AspectJProxyUtils;
import org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
import org.springframework.core.Ordered;
import org.springframework.util.ClassUtils;

/**
 * {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}
 * subclass that exposes AspectJ's invocation context and understands AspectJ's rules
 * for advice precedence when multiple pieces of advice come from the same aspect.
 *
 * @author Adrian Colyer
 * @author Juergen Hoeller
 * @author Ramnivas Laddad
 * @since 2.0
 */
@SuppressWarnings("serial")
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

	private static final Comparator DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();


	/**
	 * Sort the supplied {@link Advisor} instances according to AspectJ precedence.
	 * 

If two pieces of advice come from the same aspect, they will have the same * order. Advice from the same aspect is then further ordered according to the * following rules: *

    *
  • If either of the pair is after advice, then the advice declared * last gets highest precedence (i.e., runs last).
  • *
  • Otherwise the advice declared first gets highest precedence (i.e., runs * first).
  • *
*

Important: Advisors are sorted in precedence order, from highest * precedence to lowest. "On the way in" to a join point, the highest precedence * advisor should run first. "On the way out" of a join point, the highest * precedence advisor should run last. */ @Override protected List sortAdvisors(List advisors) { List partiallyComparableAdvisors = new ArrayList<>(advisors.size()); for (Advisor advisor : advisors) { partiallyComparableAdvisors.add( new PartiallyComparableAdvisorHolder(advisor, DEFAULT_PRECEDENCE_COMPARATOR)); } List sorted = PartialOrder.sort(partiallyComparableAdvisors); if (sorted != null) { List result = new ArrayList<>(advisors.size()); for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) { result.add(pcAdvisor.getAdvisor()); } return result; } else { return super.sortAdvisors(advisors); } } /** * Add an {@link ExposeInvocationInterceptor} to the beginning of the advice chain. *

This additional advice is needed when using AspectJ pointcut expressions * and when using AspectJ-style advice. */ @Override protected void extendAdvisors(List candidateAdvisors) { AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors); } @Override protected boolean shouldSkip(Class beanClass, String beanName) { // TODO: Consider optimization by caching the list of the aspect names List candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor && ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { return true; } } return super.shouldSkip(beanClass, beanName); } /** * Implements AspectJ's {@link PartialComparable} interface for defining partial orderings. */ private static class PartiallyComparableAdvisorHolder implements PartialComparable { private final Advisor advisor; private final Comparator comparator; public PartiallyComparableAdvisorHolder(Advisor advisor, Comparator comparator) { this.advisor = advisor; this.comparator = comparator; } @Override public int compareTo(Object obj) { Advisor otherAdvisor = ((PartiallyComparableAdvisorHolder) obj).advisor; return this.comparator.compare(this.advisor, otherAdvisor); } @Override public int fallbackCompareTo(Object obj) { return 0; } public Advisor getAdvisor() { return this.advisor; } @Override public String toString() { Advice advice = this.advisor.getAdvice(); StringBuilder sb = new StringBuilder(ClassUtils.getShortName(advice.getClass())); boolean appended = false; if (this.advisor instanceof Ordered) { sb.append(": order = ").append(((Ordered) this.advisor).getOrder()); appended = true; } if (advice instanceof AbstractAspectJAdvice) { sb.append(!appended ? ": " : ", "); AbstractAspectJAdvice ajAdvice = (AbstractAspectJAdvice) advice; sb.append("aspect name = "); sb.append(ajAdvice.getAspectName()); sb.append(", declaration order = "); sb.append(ajAdvice.getDeclarationOrder()); } return sb.toString(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy