diff --git a/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java b/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java index d3f199c501..c227150060 100644 --- a/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -97,7 +97,7 @@ public abstract class AopConfigUtils { } } - static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { + public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("exposeProxy", Boolean.TRUE); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/AspectJAutoProxyRegistrar.java b/spring-context/src/main/java/org/springframework/context/annotation/AspectJAutoProxyRegistrar.java index c73fcc7a2d..5ec21e9c3e 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/AspectJAutoProxyRegistrar.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/AspectJAutoProxyRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -27,6 +27,7 @@ import org.springframework.core.type.AnnotationMetadata; * as appropriate based on a given @{@link EnableAspectJAutoProxy} annotation. * * @author Chris Beams + * @author Juergen Hoeller * @since 3.1 * @see EnableAspectJAutoProxy */ @@ -43,11 +44,14 @@ class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); - AnnotationAttributes enableAJAutoProxy = + AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); - if (enableAJAutoProxy.getBoolean("proxyTargetClass")) { + if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } + if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { + AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); + } } } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/EnableAspectJAutoProxy.java b/spring-context/src/main/java/org/springframework/context/annotation/EnableAspectJAutoProxy.java index e2d652c875..bb82665f83 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/EnableAspectJAutoProxy.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/EnableAspectJAutoProxy.java @@ -102,6 +102,7 @@ import java.lang.annotation.Target; * } * * @author Chris Beams + * @author Juergen Hoeller * @since 3.1 * @see org.aspectj.lang.annotation.Aspect */ @@ -117,4 +118,12 @@ public @interface EnableAspectJAutoProxy { */ boolean proxyTargetClass() default false; + /** + * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} + * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. + * Off by default, i.e. no guarantees that {@code AopContext} access will work. + * @since 4.3.1 + */ + boolean exposeProxy() default false; + } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java b/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java index 2fad512225..feeee8a8ee 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java @@ -20,11 +20,13 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import example.scannable.FooService; +import example.scannable.FooServiceImpl; import example.scannable.ServiceInvocationCounter; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.junit.Test; +import org.springframework.aop.framework.AopContext; import org.springframework.aop.support.AopUtils; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; @@ -54,6 +56,14 @@ public class EnableAspectJAutoProxyTests { assertThat(AopUtils.isCglibProxy(ctx.getBean(FooService.class)), is(true)); } + @Test + public void withExposedProxy() { + ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigWithExposedProxy.class); + + aspectIsApplied(ctx); + assertThat(AopUtils.isJdkDynamicProxy(ctx.getBean(FooService.class)), is(true)); + } + private void aspectIsApplied(ApplicationContext ctx) { FooService fooService = ctx.getBean(FooService.class); ServiceInvocationCounter counter = ctx.getBean(ServiceInvocationCounter.class); @@ -101,23 +111,44 @@ public class EnableAspectJAutoProxyTests { static class ConfigWithJdkProxy { } + @ComponentScan("example.scannable") @EnableAspectJAutoProxy(proxyTargetClass = true) static class ConfigWithCglibProxy { } + @ComponentScan("example.scannable") + @EnableAspectJAutoProxy(exposeProxy = true) + static class ConfigWithExposedProxy { + + @Bean + public FooService fooServiceImpl() { + return new FooServiceImpl() { + @Override + public String foo(int id) { + assertNotNull(AopContext.currentProxy()); + return super.foo(id); + } + }; + } + } + + @Retention(RetentionPolicy.RUNTIME) public @interface Loggable { } + @Loggable public static class SampleDto { } + public static class SampleInputBean { } + public static class SampleService { // Not matched method on {@link LoggingAspect}. @@ -129,6 +160,7 @@ public class EnableAspectJAutoProxyTests { } } + @Aspect public static class LoggingAspect {