diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisorChainFactory.java b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisorChainFactory.java index a912aa9a88..a8774fa7be 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisorChainFactory.java +++ b/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"); * 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. * @param config the AOP configuration in the form of an Advised object * @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) */ - List getInterceptorsAndDynamicInterceptionAdvice( - Advised config, Method method, Class targetClass); + List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class targetClass); } diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAdvisorChainFactory.java b/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAdvisorChainFactory.java index d99607cae1..740a7bb8ff 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAdvisorChainFactory.java +++ b/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"); * you may not use this file except in compliance with the License. @@ -50,19 +50,21 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ public List getInterceptorsAndDynamicInterceptionAdvice( 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. List interceptorList = new ArrayList(config.getAdvisors().length); - boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); + Class actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); + boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); + for (Advisor advisor : config.getAdvisors()) { if (advisor instanceof PointcutAdvisor) { // Add it conditionally. 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); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); - if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { + if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // 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) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; - if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { + if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } @@ -88,18 +90,19 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ interceptorList.addAll(Arrays.asList(interceptors)); } } + return interceptorList; } /** * 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++) { Advisor advisor = config.getAdvisors()[i]; if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; - if (ia.getClassFilter().matches(targetClass)) { + if (ia.getClassFilter().matches(actualClass)) { return true; } } diff --git a/spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerFactoryBeanIntegrationTests.java b/spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerFactoryBeanIntegrationTests.java index 887e02a23d..6662037d4c 100644 --- a/spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerFactoryBeanIntegrationTests.java +++ b/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.Configuration; 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 static org.junit.Assert.*; /** - * * @author Stephane Nicoll */ public class HttpInvokerFactoryBeanIntegrationTests { @@ -42,6 +45,8 @@ public class HttpInvokerFactoryBeanIntegrationTests { ApplicationContext context = new AnnotationConfigApplicationContext(InvokerAutowiringConfig.class); MyBean myBean = context.getBean("myBean", MyBean.class); assertSame(context.getBean("myService"), myBean.myService); + myBean.myService.handle(); + myBean.myService.handleAsync(); } @Test @@ -51,10 +56,17 @@ public class HttpInvokerFactoryBeanIntegrationTests { context.refresh(); MyBean myBean = context.getBean("myBean", MyBean.class); assertSame(context.getBean("myService"), myBean.myService); + myBean.myService.handle(); + myBean.myService.handleAsync(); } public interface MyService { + + public void handle(); + + @Async + public void handleAsync(); } @@ -62,7 +74,7 @@ public class HttpInvokerFactoryBeanIntegrationTests { public static class MyBean { @Autowired - private MyService myService; + public MyService myService; } @@ -71,11 +83,23 @@ public class HttpInvokerFactoryBeanIntegrationTests { @Lazy public static class InvokerAutowiringConfig { + @Bean + public AsyncAnnotationBeanPostProcessor aabpp() { + return new AsyncAnnotationBeanPostProcessor(); + } + @Bean public HttpInvokerProxyFactoryBean myService() { HttpInvokerProxyFactoryBean factory = new HttpInvokerProxyFactoryBean(); factory.setServiceUrl("/svc/dummy"); 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; }