+ * @Configuration
+ * @EnableAspectJAutoProxy
+ * public class AppConfig {
+ * @Bean
+ * public FooService fooService() {
+ * return new FooService();
+ * }
+ *
+ * @Bean
+ * public MyAspect myAspect() {
+ * return new MyAspect();
+ * }
+ * }
+ *
+ * Where {@code FooService} is a typical POJO component and {@code MyAspect} is an
+ * {@code @Aspect}-style aspect:
+ *
+ *
+ * public class FooService {
+ * // various methods
+ * }
+ *
+ *
+ * @Aspect
+ * public class MyAspect {
+ * @Before("execution(* FooService+.*(..))")
+ * public void advice() {
+ * // advise FooService methods as appropriate
+ * }
+ * }
+ *
+ * In the scenario above, {@code @EnableAspectJAutoProxy} ensures that {@code MyAspect}
+ * will be properly processed and that {@code FooService} will be proxied mixing in the
+ * advice that it contributes.
+ *
+ * Users can control the type of proxy that gets created for {@code FooService} using + * the {@link #proxyTargetClass()} attribute. The following enables CGLIB-style 'subclass' + * proxies as opposed to the default interface-based JDK proxy approach. + *
+ * @Configuration
+ * @EnableAspectJAutoProxy(proxyTargetClass=true)
+ * public class AppConfig {
+ * // ...
+ * }
+ *
+ * Note that {@code @Aspect} beans may be component-scanned like any other. Simply + * mark the aspect with both {@code @Aspect} and {@code @Component}: + *
+ * package com.foo;
+ *
+ * @Component
+ * public class FooService { ... }
+ *
+ * @Aspect
+ * @Component
+ * public class MyAspect { ... }
+ *
+ * Then use the @{@link ComponentScan} annotation to pick both up:
+ *
+ * @Configuration
+ * @ComponentScan("com.foo")
+ * @EnableAspectJAutoProxy
+ * public class AppConfig {
+ * // no explicit @Bean definitions required
+ * }
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see org.aspectj.lang.annotation.Aspect
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Import(AspectJAutoProxyConfigurationSelector.class)
+@Documented
+public @interface EnableAspectJAutoProxy {
+
+ /**
+ * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
+ * to standard Java interface-based proxies. The default is {@code false}.
+ */
+ boolean proxyTargetClass() default false;
+
+}
diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java
new file mode 100644
index 0000000000..444d4ed257
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2008 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
+ *
+import org.springframework.aop.aspectj.annotation.EnableAspectJAutoProxy;
+
+ * http://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.context.annotation;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.context.ApplicationContext;
+
+import example.scannable.FooService;
+import example.scannable.ServiceInvocationCounter;
+
+/**
+ * @author Juergen Hoeller
+ * @author Chris Beams
+ */
+public class EnableAspectJAutoProxyTests {
+
+ @Configuration
+ @ComponentScan("example.scannable")
+ @EnableAspectJAutoProxy
+ static class Config_WithJDKProxy {
+ }
+
+ @Configuration
+ @ComponentScan("example.scannable")
+ @EnableAspectJAutoProxy(proxyTargetClass=true)
+ static class Config_WithCGLIBProxy {
+ }
+
+ @Test
+ public void withJDKProxy() throws Exception {
+ ApplicationContext ctx =
+ new AnnotationConfigApplicationContext(Config_WithJDKProxy.class);
+
+ aspectIsApplied(ctx);
+ assertThat(AopUtils.isJdkDynamicProxy(ctx.getBean(FooService.class)), is(true));
+ }
+
+ @Test
+ public void withCGLIBProxy() throws Exception {
+ ApplicationContext ctx =
+ new AnnotationConfigApplicationContext(Config_WithCGLIBProxy.class);
+
+ aspectIsApplied(ctx);
+ assertThat(AopUtils.isCglibProxy(ctx.getBean(FooService.class)), is(true));
+ }
+
+
+ private void aspectIsApplied(ApplicationContext ctx) throws Exception {
+ FooService fooService = ctx.getBean(FooService.class);
+ ServiceInvocationCounter counter = ctx.getBean(ServiceInvocationCounter.class);
+
+ assertEquals(0, counter.getCount());
+
+ assertTrue(fooService.isInitCalled());
+ assertEquals(1, counter.getCount());
+
+ String value = fooService.foo(1);
+ assertEquals("bar", value);
+ assertEquals(2, counter.getCount());
+
+ fooService.foo(1);
+ assertEquals(3, counter.getCount());
+ }
+}
\ No newline at end of file
diff --git a/spring-framework-reference/src/new-in-3.1.xml b/spring-framework-reference/src/new-in-3.1.xml
index afdb052d51..b73e5c7a5e 100644
--- a/spring-framework-reference/src/new-in-3.1.xml
+++ b/spring-framework-reference/src/new-in-3.1.xml
@@ -128,6 +128,12 @@
Javadoc
+