revised advice ordering (for async execution interceptor)

This commit is contained in:
Juergen Hoeller 2009-02-09 18:32:21 +00:00
parent fc6d7358ef
commit 0794756fba
4 changed files with 34 additions and 32 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.springframework.aop.aspectj.annotation; package org.springframework.aop.aspectj.annotation;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -27,6 +28,7 @@ import org.springframework.aop.aspectj.AspectJProxyUtils;
import org.springframework.aop.framework.AopConfigException; import org.springframework.aop.framework.AopConfigException;
import org.springframework.aop.framework.ProxyCreatorSupport; import org.springframework.aop.framework.ProxyCreatorSupport;
import org.springframework.aop.support.AopUtils; import org.springframework.aop.support.AopUtils;
import org.springframework.core.OrderComparator;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@ -116,10 +118,11 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
* @see #makeAdvisorChainAspectJCapableIfNecessary() * @see #makeAdvisorChainAspectJCapableIfNecessary()
*/ */
private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) { private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
List advisors = this.aspectFactory.getAdvisors(instanceFactory); List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass()); advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
addAllAdvisors((Advisor[]) advisors.toArray(new Advisor[advisors.size()])); AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
makeAdvisorChainAspectJCapableIfNecessary(); Collections.sort(advisors, new OrderComparator());
addAdvisors(advisors);
} }
/** /**
@ -154,18 +157,6 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
return instanceFactory; return instanceFactory;
} }
/**
* Add any special-purpose {@link Advisor Advisors} needed for AspectJ support
* to the chain. {@link #updateAdvisorArray() Updates} the {@link Advisor} array
* and fires {@link #adviceChanged events}.
*/
private void makeAdvisorChainAspectJCapableIfNecessary() {
if (AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(getAdvisorsInternal())) {
updateAdvisorArray();
adviceChanged();
}
}
/** /**
* Get the singleton aspect instance for the supplied aspect type. An instance * Get the singleton aspect instance for the supplied aspect type. An instance
* is created if one cannot be found in the instance cache. * is created if one cannot be found in the instance cache.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -86,10 +86,10 @@ public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyC
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) { protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) { if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors); eligibleAdvisors = sortAdvisors(eligibleAdvisors);
} }
extendAdvisors(eligibleAdvisors);
return eligibleAdvisors; return eligibleAdvisors;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,6 +24,7 @@ import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor; import org.springframework.aop.Advisor;
import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.core.NamedThreadLocal; import org.springframework.core.NamedThreadLocal;
import org.springframework.core.Ordered;
/** /**
* Interceptor that exposes the current {@link org.aopalliance.intercept.MethodInvocation} * Interceptor that exposes the current {@link org.aopalliance.intercept.MethodInvocation}
@ -39,7 +40,7 @@ import org.springframework.core.NamedThreadLocal;
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
*/ */
public class ExposeInvocationInterceptor implements MethodInterceptor, Serializable { public class ExposeInvocationInterceptor implements MethodInterceptor, Ordered, Serializable {
/** Singleton instance of this class */ /** Singleton instance of this class */
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor(); public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
@ -49,17 +50,14 @@ public class ExposeInvocationInterceptor implements MethodInterceptor, Serializa
* Spring AOP, as it prevents the need to create a new Advisor to wrap the instance. * Spring AOP, as it prevents the need to create a new Advisor to wrap the instance.
*/ */
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) { public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
@Override
public int getOrder() {
return Integer.MIN_VALUE;
}
@Override @Override
public String toString() { public String toString() {
return ExposeInvocationInterceptor.class.getName() +".ADVISOR"; return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
} }
}; };
private static final ThreadLocal invocation = new NamedThreadLocal("Current AOP method invocation"); private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<MethodInvocation>("Current AOP method invocation");
/** /**
@ -69,7 +67,7 @@ public class ExposeInvocationInterceptor implements MethodInterceptor, Serializa
* or if the ExposeInvocationInterceptor was not added to this interceptor chain * or if the ExposeInvocationInterceptor was not added to this interceptor chain
*/ */
public static MethodInvocation currentInvocation() throws IllegalStateException { public static MethodInvocation currentInvocation() throws IllegalStateException {
MethodInvocation mi = (MethodInvocation) invocation.get(); MethodInvocation mi = invocation.get();
if (mi == null) if (mi == null)
throw new IllegalStateException( throw new IllegalStateException(
"No MethodInvocation found: Check that an AOP invocation is in progress, " + "No MethodInvocation found: Check that an AOP invocation is in progress, " +
@ -85,16 +83,20 @@ public class ExposeInvocationInterceptor implements MethodInterceptor, Serializa
} }
public Object invoke(MethodInvocation mi) throws Throwable { public Object invoke(MethodInvocation mi) throws Throwable {
Object old = invocation.get(); MethodInvocation oldInvocation = invocation.get();
invocation.set(mi); invocation.set(mi);
try { try {
return mi.proceed(); return mi.proceed();
} }
finally { finally {
invocation.set(old); invocation.set(oldInvocation);
} }
} }
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE + 1;
}
/** /**
* Required to support serialization. Replaces with canonical instance * Required to support serialization. Replaces with canonical instance
* on deserialization, protecting Singleton pattern. * on deserialization, protecting Singleton pattern.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,8 @@ package org.springframework.aop.support;
import java.io.Serializable; import java.io.Serializable;
import org.aopalliance.aop.Advice;
import org.springframework.aop.PointcutAdvisor; import org.springframework.aop.PointcutAdvisor;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@ -34,7 +36,7 @@ import org.springframework.util.ObjectUtils;
*/ */
public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordered, Serializable { public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordered, Serializable {
private int order = Ordered.LOWEST_PRECEDENCE; private Integer order;
public void setOrder(int order) { public void setOrder(int order) {
@ -42,8 +44,15 @@ public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordere
} }
public int getOrder() { public int getOrder() {
if (this.order != null) {
return this.order; return this.order;
} }
Advice advice = getAdvice();
if (advice instanceof Ordered) {
return ((Ordered) advice).getOrder();
}
return Ordered.LOWEST_PRECEDENCE;
}
public boolean isPerInstance() { public boolean isPerInstance() {
return true; return true;