Browse Source

DefaultAdvisorChainFactory never passes null into ClassFilter, enabling async advisor to work without target class as well

Issue: SPR-11910
pull/568/merge
Juergen Hoeller 12 years ago
parent
commit
a9b650fd0f
  1. 8
      spring-aop/src/main/java/org/springframework/aop/framework/AdvisorChainFactory.java
  2. 19
      spring-aop/src/main/java/org/springframework/aop/framework/DefaultAdvisorChainFactory.java
  3. 28
      spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerFactoryBeanIntegrationTests.java

8
spring-aop/src/main/java/org/springframework/aop/framework/AdvisorChainFactory.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2014 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.
@ -32,10 +32,10 @@ public interface AdvisorChainFactory {
* for the given advisor chain configuration. * for the given advisor chain configuration.
* @param config the AOP configuration in the form of an Advised object * @param config the AOP configuration in the form of an Advised object
* @param method the proxied method * @param method the proxied method
* @param targetClass the target class * @param targetClass the target class (may be {@code null} to indicate a proxy without
* target object, in which case the method's declaring class is the next best option)
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers) * @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/ */
List<Object> getInterceptorsAndDynamicInterceptionAdvice( List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass);
Advised config, Method method, Class<?> targetClass);
} }

19
spring-aop/src/main/java/org/springframework/aop/framework/DefaultAdvisorChainFactory.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -50,19 +50,21 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
public List<Object> getInterceptorsAndDynamicInterceptionAdvice( public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) { Advised config, Method method, Class<?> targetClass) {
// This is somewhat tricky... we have to process introductions first, // This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list. // but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length); List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) { for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) { if (advisor instanceof PointcutAdvisor) {
// Add it conditionally. // Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) { if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method // Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains. // isn't a problem as we normally cache created chains.
@ -78,7 +80,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
} }
else if (advisor instanceof IntroductionAdvisor) { else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor; IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor); Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors)); interceptorList.addAll(Arrays.asList(interceptors));
} }
@ -88,18 +90,19 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
interceptorList.addAll(Arrays.asList(interceptors)); interceptorList.addAll(Arrays.asList(interceptors));
} }
} }
return interceptorList; return interceptorList;
} }
/** /**
* Determine whether the Advisors contain matching introductions. * Determine whether the Advisors contain matching introductions.
*/ */
private static boolean hasMatchingIntroductions(Advised config, Class<?> targetClass) { private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
for (int i = 0; i < config.getAdvisors().length; i++) { for (int i = 0; i < config.getAdvisors().length; i++) {
Advisor advisor = config.getAdvisors()[i]; Advisor advisor = config.getAdvisors()[i];
if (advisor instanceof IntroductionAdvisor) { if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor; IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(targetClass)) { if (ia.getClassFilter().matches(actualClass)) {
return true; return true;
} }
} }

28
spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerFactoryBeanIntegrationTests.java

@ -27,12 +27,15 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.remoting.support.RemoteInvocation;
import org.springframework.remoting.support.RemoteInvocationResult;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
*
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
public class HttpInvokerFactoryBeanIntegrationTests { public class HttpInvokerFactoryBeanIntegrationTests {
@ -42,6 +45,8 @@ public class HttpInvokerFactoryBeanIntegrationTests {
ApplicationContext context = new AnnotationConfigApplicationContext(InvokerAutowiringConfig.class); ApplicationContext context = new AnnotationConfigApplicationContext(InvokerAutowiringConfig.class);
MyBean myBean = context.getBean("myBean", MyBean.class); MyBean myBean = context.getBean("myBean", MyBean.class);
assertSame(context.getBean("myService"), myBean.myService); assertSame(context.getBean("myService"), myBean.myService);
myBean.myService.handle();
myBean.myService.handleAsync();
} }
@Test @Test
@ -51,10 +56,17 @@ public class HttpInvokerFactoryBeanIntegrationTests {
context.refresh(); context.refresh();
MyBean myBean = context.getBean("myBean", MyBean.class); MyBean myBean = context.getBean("myBean", MyBean.class);
assertSame(context.getBean("myService"), myBean.myService); assertSame(context.getBean("myService"), myBean.myService);
myBean.myService.handle();
myBean.myService.handleAsync();
} }
public interface MyService { public interface MyService {
public void handle();
@Async
public void handleAsync();
} }
@ -62,7 +74,7 @@ public class HttpInvokerFactoryBeanIntegrationTests {
public static class MyBean { public static class MyBean {
@Autowired @Autowired
private MyService myService; public MyService myService;
} }
@ -71,11 +83,23 @@ public class HttpInvokerFactoryBeanIntegrationTests {
@Lazy @Lazy
public static class InvokerAutowiringConfig { public static class InvokerAutowiringConfig {
@Bean
public AsyncAnnotationBeanPostProcessor aabpp() {
return new AsyncAnnotationBeanPostProcessor();
}
@Bean @Bean
public HttpInvokerProxyFactoryBean myService() { public HttpInvokerProxyFactoryBean myService() {
HttpInvokerProxyFactoryBean factory = new HttpInvokerProxyFactoryBean(); HttpInvokerProxyFactoryBean factory = new HttpInvokerProxyFactoryBean();
factory.setServiceUrl("/svc/dummy"); factory.setServiceUrl("/svc/dummy");
factory.setServiceInterface(MyService.class); factory.setServiceInterface(MyService.class);
Thread thread = Thread.currentThread();
factory.setHttpInvokerRequestExecutor(new HttpInvokerRequestExecutor() {
@Override
public RemoteInvocationResult executeRequest(HttpInvokerClientConfiguration config, RemoteInvocation invocation) {
return new RemoteInvocationResult(null);
}
});
return factory; return factory;
} }

Loading…
Cancel
Save