diff --git a/framework-docs/framework-docs.gradle b/framework-docs/framework-docs.gradle
index 50f4dd1ea3..374e267096 100644
--- a/framework-docs/framework-docs.gradle
+++ b/framework-docs/framework-docs.gradle
@@ -65,6 +65,7 @@ dependencies {
api(project(":spring-web"))
api(project(":spring-webmvc"))
api(project(":spring-context-support"))
+ api(project(":spring-aspects"))
api("org.jetbrains.kotlin:kotlin-stdlib")
api("jakarta.jms:jakarta.jms-api")
@@ -74,6 +75,7 @@ dependencies {
api("com.fasterxml.jackson.core:jackson-databind")
api("com.fasterxml.jackson.module:jackson-module-parameter-names")
api("jakarta.validation:jakarta.validation-api")
+ api("org.aspectj:aspectjweaver")
implementation(project(":spring-core-test"))
implementation("org.assertj:assertj-core")
diff --git a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/aspectj-support.adoc b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/aspectj-support.adoc
index 6bbddeaddb..f3dae9e6d1 100644
--- a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/aspectj-support.adoc
+++ b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/aspectj-support.adoc
@@ -8,54 +8,8 @@ determines that a bean is advised by one or more aspects, it automatically gener
a proxy for that bean to intercept method invocations and ensures that advice is run
as needed.
-The @AspectJ support can be enabled with XML- or Java-style configuration. In either
-case, you also need to ensure that AspectJ's `aspectjweaver.jar` library is on the
-classpath of your application (version 1.9 or later). This library is available in the
-`lib` directory of an AspectJ distribution or from the Maven Central repository.
-
-
-[[aop-enable-aspectj-java]]
-== Enabling @AspectJ Support with Java Configuration
-
-To enable @AspectJ support with Java `@Configuration`, add the `@EnableAspectJAutoProxy`
-annotation, as the following example shows:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary"]
-----
- @Configuration
- @EnableAspectJAutoProxy
- public class AppConfig {
- }
-----
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary"]
-----
- @Configuration
- @EnableAspectJAutoProxy
- class AppConfig
-----
-======
-
-[[aop-enable-aspectj-xml]]
-== Enabling @AspectJ Support with XML Configuration
-
-To enable @AspectJ support with XML-based configuration, use the `aop:aspectj-autoproxy`
-element, as the following example shows:
-
-[source,xml,indent=0,subs="verbatim"]
-----
-
-----
-
-This assumes that you use schema support as described in
-xref:core/appendix/xsd-schemas.adoc[XML Schema-based configuration].
-See xref:core/appendix/xsd-schemas.adoc#aop[the AOP schema] for how to
-import the tags in the `aop` namespace.
-
-
+The @AspectJ support can be enabled with programmatic or XML configuration. In either
+case, you also need to ensure that AspectJ's `org.aspectj:aspectjweaver` library is on the
+classpath of your application (version 1.9 or later).
+include-code::./ApplicationConfiguration[tag=snippet,indent=0]
diff --git a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/at-aspectj.adoc b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/at-aspectj.adoc
index 5e2e40176e..4672c2d547 100644
--- a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/at-aspectj.adoc
+++ b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/at-aspectj.adoc
@@ -9,43 +9,12 @@ minimal steps required for a not-very-useful aspect.
The first of the two examples shows a regular bean definition in the application context
that points to a bean class that is annotated with `@Aspect`:
-[source,xml,indent=0,subs="verbatim"]
-----
-
-
-
-----
+include-code::./ApplicationConfiguration[tag=snippet,indent=0]
The second of the two examples shows the `NotVeryUsefulAspect` class definition, which is
annotated with `@Aspect`:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages",fold="none"]
-----
- package com.xyz;
-
- import org.aspectj.lang.annotation.Aspect;
-
- @Aspect
- public class NotVeryUsefulAspect {
- }
-----
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages",fold="none"]
-----
- package com.xyz
-
- import org.aspectj.lang.annotation.Aspect
-
- @Aspect
- class NotVeryUsefulAspect
-----
-======
+include-code::./NotVeryUsefulAspect[tag=snippet,indent=0]
Aspects (classes annotated with `@Aspect`) can have methods and fields, the same as any
other class. They can also contain pointcut, advice, and introduction (inter-type)
diff --git a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/example.adoc b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/example.adoc
index 896086c928..6fd5e242bf 100644
--- a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/example.adoc
+++ b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/example.adoc
@@ -16,93 +16,9 @@ aspect.
Because we want to retry the operation, we need to use around advice so that we can
call `proceed` multiple times. The following listing shows the basic aspect implementation:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary"]
-----
- @Aspect
- public class ConcurrentOperationExecutor implements Ordered {
+include-code::./ConcurrentOperationExecutor[tag=snippet,indent=0]
- private static final int DEFAULT_MAX_RETRIES = 2;
-
- private int maxRetries = DEFAULT_MAX_RETRIES;
- private int order = 1;
-
- public void setMaxRetries(int maxRetries) {
- this.maxRetries = maxRetries;
- }
-
- public int getOrder() {
- return this.order;
- }
-
- public void setOrder(int order) {
- this.order = order;
- }
-
- @Around("com.xyz.CommonPointcuts.businessService()") // <1>
- public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
- int numAttempts = 0;
- PessimisticLockingFailureException lockFailureException;
- do {
- numAttempts++;
- try {
- return pjp.proceed();
- }
- catch(PessimisticLockingFailureException ex) {
- lockFailureException = ex;
- }
- } while(numAttempts <= this.maxRetries);
- throw lockFailureException;
- }
- }
-----
-<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary"]
-----
- @Aspect
- class ConcurrentOperationExecutor : Ordered {
-
- private val DEFAULT_MAX_RETRIES = 2
- private var maxRetries = DEFAULT_MAX_RETRIES
- private var order = 1
-
- fun setMaxRetries(maxRetries: Int) {
- this.maxRetries = maxRetries
- }
-
- override fun getOrder(): Int {
- return this.order
- }
-
- fun setOrder(order: Int) {
- this.order = order
- }
-
- @Around("com.xyz.CommonPointcuts.businessService()") // <1>
- fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
- var numAttempts = 0
- var lockFailureException: PessimisticLockingFailureException
- do {
- numAttempts++
- try {
- return pjp.proceed()
- } catch (ex: PessimisticLockingFailureException) {
- lockFailureException = ex
- }
-
- } while (numAttempts <= this.maxRetries)
- throw lockFailureException
- }
- }
-----
-<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
-======
+`@Around("com.xyz.CommonPointcuts.businessService()")` references the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
Note that the aspect implements the `Ordered` interface so that we can set the precedence of
the aspect higher than the transaction advice (we want a fresh transaction each time we
@@ -114,70 +30,15 @@ we have exhausted all of our retry attempts.
The corresponding Spring configuration follows:
-[source,xml,indent=0,subs="verbatim"]
-----
-
-
-
-
-
-
-----
+include-code::./ApplicationConfiguration[tag=snippet,indent=0]
To refine the aspect so that it retries only idempotent operations, we might define the following
`Idempotent` annotation:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary"]
-----
- @Retention(RetentionPolicy.RUNTIME)
- // marker annotation
- public @interface Idempotent {
- }
-----
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary"]
-----
- @Retention(AnnotationRetention.RUNTIME)
- // marker annotation
- annotation class Idempotent
-----
-======
+include-code::./service/Idempotent[tag=snippet,indent=0]
We can then use the annotation to annotate the implementation of service operations. The change
to the aspect to retry only idempotent operations involves refining the pointcut
expression so that only `@Idempotent` operations match, as follows:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary"]
-----
- @Around("execution(* com.xyz..service.*.*(..)) && " +
- "@annotation(com.xyz.service.Idempotent)")
- public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
- // ...
- }
-----
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary"]
-----
- @Around("execution(* com.xyz..service.*.*(..)) && " +
- "@annotation(com.xyz.service.Idempotent)")
- fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
- // ...
- }
-----
-======
-
-
-
+include-code::./service/SampleService[tag=snippet,indent=0]
diff --git a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/introductions.adoc b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/introductions.adoc
index e8732d3cc3..1c84a3beb7 100644
--- a/framework-docs/modules/ROOT/pages/core/aop/ataspectj/introductions.adoc
+++ b/framework-docs/modules/ROOT/pages/core/aop/ataspectj/introductions.adoc
@@ -72,7 +72,7 @@ Kotlin::
+
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
----
- val usageTracked = context.getBean("myService", UsageTracked.class)
+ val usageTracked = context.getBean("myService")
----
======
diff --git a/framework-docs/modules/ROOT/pages/core/aop/using-aspectj.adoc b/framework-docs/modules/ROOT/pages/core/aop/using-aspectj.adoc
index f17d62e2f3..c9176447eb 100644
--- a/framework-docs/modules/ROOT/pages/core/aop/using-aspectj.adoc
+++ b/framework-docs/modules/ROOT/pages/core/aop/using-aspectj.adoc
@@ -66,7 +66,7 @@ Kotlin::
When used as a marker interface in this way, Spring configures new instances of the
annotated type (`Account`, in this case) by using a bean definition (typically
prototype-scoped) with the same name as the fully-qualified type name
-(`com.xyz.domain.Account`). Since the default name for a bean is the
+(`com.xyz.domain.Account`). Since the default name for a bean defined via XML is the
fully-qualified name of its type, a convenient way to declare the prototype definition
is to omit the `id` attribute, as the following example shows:
@@ -177,41 +177,10 @@ either use a build-time Ant or Maven task to do this (see, for example, the
{aspectj-docs-devguide}/antTasks.html[AspectJ Development
Environment Guide]) or load-time weaving (see xref:core/aop/using-aspectj.adoc#aop-aj-ltw[Load-time Weaving with AspectJ in the Spring Framework]). The
`AnnotationBeanConfigurerAspect` itself needs to be configured by Spring (in order to obtain
-a reference to the bean factory that is to be used to configure new objects). If you
-use Java-based configuration, you can add `@EnableSpringConfigured` to any
-`@Configuration` class, as follows:
+a reference to the bean factory that is to be used to configure new objects). You can define
+the related configuration as follows:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary"]
-----
- @Configuration
- @EnableSpringConfigured
- public class AppConfig {
- }
-----
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary"]
-----
- @Configuration
- @EnableSpringConfigured
- class AppConfig {
- }
-----
-======
-
-If you prefer XML based configuration, the Spring
-xref:core/appendix/xsd-schemas.adoc#context[`context` namespace]
-defines a convenient `context:spring-configured` element, which you can use as follows:
-
-[source,xml,indent=0,subs="verbatim"]
-----
-
-----
+include-code::./ApplicationConfiguration[tag=snippet,indent=0]
Instances of `@Configurable` objects created before the aspect has been configured
result in a message being issued to the debug log and no configuration of the
@@ -783,52 +752,9 @@ adding one line. (Note that you almost certainly need to use an
`ApplicationContext` as your Spring container -- typically, a `BeanFactory` is not
enough because the LTW support uses `BeanFactoryPostProcessors`.)
-To enable the Spring Framework's LTW support, you need to configure a `LoadTimeWeaver`,
-which typically is done by using the `@EnableLoadTimeWeaving` annotation, as follows:
+To enable the Spring Framework's LTW support, you need to configure a `LoadTimeWeaver` as follows:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary"]
-----
- @Configuration
- @EnableLoadTimeWeaving
- public class AppConfig {
- }
-----
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary"]
-----
- @Configuration
- @EnableLoadTimeWeaving
- class AppConfig {
- }
-----
-======
-
-Alternatively, if you prefer XML-based configuration, use the
-`` element. Note that the element is defined in the
-`context` namespace. The following example shows how to use ``:
-
-[source,xml,indent=0,subs="verbatim"]
-----
-
-
-
-
-
-
-----
+include-code::./ApplicationConfiguration[tag=snippet,indent=0]
The preceding configuration automatically defines and registers a number of LTW-specific
infrastructure beans, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`, for you.
@@ -864,63 +790,12 @@ Note that the table lists only the `LoadTimeWeavers` that are autodetected when
use the `DefaultContextLoadTimeWeaver`. You can specify exactly which `LoadTimeWeaver`
implementation to use.
-To specify a specific `LoadTimeWeaver` with Java configuration, implement the
-`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method.
+To configure a specific `LoadTimeWeaver`, implement the
+`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method
+(or use the XML equivalent).
The following example specifies a `ReflectiveLoadTimeWeaver`:
-[tabs]
-======
-Java::
-+
-[source,java,indent=0,subs="verbatim",role="primary"]
-----
- @Configuration
- @EnableLoadTimeWeaving
- public class AppConfig implements LoadTimeWeavingConfigurer {
-
- @Override
- public LoadTimeWeaver getLoadTimeWeaver() {
- return new ReflectiveLoadTimeWeaver();
- }
- }
-----
-
-Kotlin::
-+
-[source,kotlin,indent=0,subs="verbatim",role="secondary"]
-----
- @Configuration
- @EnableLoadTimeWeaving
- class AppConfig : LoadTimeWeavingConfigurer {
-
- override fun getLoadTimeWeaver(): LoadTimeWeaver {
- return ReflectiveLoadTimeWeaver()
- }
- }
-----
-======
-
-If you use XML-based configuration, you can specify the fully qualified class name
-as the value of the `weaver-class` attribute on the ``
-element. Again, the following example specifies a `ReflectiveLoadTimeWeaver`:
-
-[source,xml,indent=0,subs="verbatim"]
-----
-
-
-
-
-
-
-----
+include-code::./CustomWeaverConfiguration[tag=snippet,indent=0]
The `LoadTimeWeaver` that is defined and registered by the configuration can be later
retrieved from the Spring container by using the well known name, `loadTimeWeaver`.
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.java
new file mode 100644
index 0000000000..4f1456b36e
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.aopajltwspring;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableLoadTimeWeaving;
+
+// tag::snippet[]
+@Configuration
+@EnableLoadTimeWeaving
+public class ApplicationConfiguration {
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.java
new file mode 100644
index 0000000000..0a51c937e2
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.aopajltwspring;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableLoadTimeWeaving;
+import org.springframework.context.annotation.LoadTimeWeavingConfigurer;
+import org.springframework.instrument.classloading.LoadTimeWeaver;
+import org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver;
+
+// tag::snippet[]
+@Configuration
+@EnableLoadTimeWeaving
+public class CustomWeaverConfiguration implements LoadTimeWeavingConfigurer {
+
+ @Override
+ public LoadTimeWeaver getLoadTimeWeaver() {
+ return new ReflectiveLoadTimeWeaver();
+ }
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.java
new file mode 100644
index 0000000000..a7b6bb6496
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.aopatconfigurable;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
+
+// tag::snippet[]
+@Configuration
+@EnableSpringConfigured
+public class ApplicationConfiguration {
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.java
new file mode 100644
index 0000000000..a45001fdad
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopaspectjsupport;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+// tag::snippet[]
+@Configuration
+@EnableAspectJAutoProxy
+public class ApplicationConfiguration {
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.java
new file mode 100644
index 0000000000..522acd7ea6
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectj;
+
+import org.springframework.context.annotation.Bean;
+
+// tag::snippet[]
+public class ApplicationConfiguration {
+
+ @Bean
+ public NotVeryUsefulAspect myAspect() {
+ NotVeryUsefulAspect myAspect = new NotVeryUsefulAspect();
+ // Configure properties of the aspect here
+ return myAspect;
+ }
+}
+// end::snippet[]
\ No newline at end of file
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.java
new file mode 100644
index 0000000000..337fe12651
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectj;
+
+import org.aspectj.lang.annotation.Aspect;
+
+// tag::snippet[]
+@Aspect
+public class NotVeryUsefulAspect {
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.java
new file mode 100644
index 0000000000..abba619211
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+// tag::snippet[]
+@Configuration
+@EnableAspectJAutoProxy
+public class ApplicationConfiguration {
+
+ @Bean
+ public ConcurrentOperationExecutor concurrentOperationExecutor() {
+ ConcurrentOperationExecutor executor = new ConcurrentOperationExecutor();
+ executor.setMaxRetries(3);
+ executor.setOrder(100);
+ return executor;
+
+ }
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.java
new file mode 100644
index 0000000000..a760f74491
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+
+import org.springframework.core.Ordered;
+import org.springframework.dao.PessimisticLockingFailureException;
+
+// tag::snippet[]
+@Aspect
+public class ConcurrentOperationExecutor implements Ordered {
+
+ private static final int DEFAULT_MAX_RETRIES = 2;
+
+ private int maxRetries = DEFAULT_MAX_RETRIES;
+ private int order = 1;
+
+ public void setMaxRetries(int maxRetries) {
+ this.maxRetries = maxRetries;
+ }
+
+ public int getOrder() {
+ return this.order;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ @Around("com.xyz.CommonPointcuts.businessService()")
+ public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
+ int numAttempts = 0;
+ PessimisticLockingFailureException lockFailureException;
+ do {
+ numAttempts++;
+ try {
+ return pjp.proceed();
+ }
+ catch(PessimisticLockingFailureException ex) {
+ lockFailureException = ex;
+ }
+ } while(numAttempts <= this.maxRetries);
+ throw lockFailureException;
+ }
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.java
new file mode 100644
index 0000000000..394f21b43a
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample.service;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+// tag::snippet[]
+@Retention(RetentionPolicy.RUNTIME)
+// marker annotation
+public @interface Idempotent {
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.java b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.java
new file mode 100644
index 0000000000..70636063a6
--- /dev/null
+++ b/framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample.service;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class SampleService {
+
+ // tag::snippet[]
+ @Around("execution(* com.xyz..service.*.*(..)) && " +
+ "@annotation(com.xyz.service.Idempotent)")
+ public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
+ // ...
+ return pjp.proceed(pjp.getArgs());
+ }
+ // end::snippet[]
+
+}
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.kt
new file mode 100644
index 0000000000..8c5635a641
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.aopajltwspring
+
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.EnableLoadTimeWeaving
+
+// tag::snippet[]
+@Configuration
+@EnableLoadTimeWeaving
+class ApplicationConfiguration
+// end::snippet[]
\ No newline at end of file
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.kt
new file mode 100644
index 0000000000..587efae332
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.aopajltwspring
+
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.EnableLoadTimeWeaving
+import org.springframework.context.annotation.LoadTimeWeavingConfigurer
+import org.springframework.instrument.classloading.LoadTimeWeaver
+import org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver
+
+// tag::snippet[]
+@Configuration
+@EnableLoadTimeWeaving
+class CustomWeaverConfiguration : LoadTimeWeavingConfigurer {
+
+ override fun getLoadTimeWeaver(): LoadTimeWeaver {
+ return ReflectiveLoadTimeWeaver()
+ }
+}
+// end::snippet[]
\ No newline at end of file
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.kt
new file mode 100644
index 0000000000..ff92f4e372
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.aopatconfigurable
+
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.aspectj.EnableSpringConfigured
+
+// tag::snippet[]
+@Configuration
+@EnableSpringConfigured
+class ApplicationConfiguration
+// end::snippet[]
\ No newline at end of file
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.kt
new file mode 100644
index 0000000000..ca3544a399
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopaspectjsupport
+
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.EnableAspectJAutoProxy
+
+// tag::snippet[]
+@Configuration
+@EnableAspectJAutoProxy
+class ApplicationConfiguration
+// end::snippet[]
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.kt
new file mode 100644
index 0000000000..ebeb56710f
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectj
+
+import org.springframework.context.annotation.Bean
+
+// tag::snippet[]
+class ApplicationConfiguration {
+
+ @Bean
+ fun myAspect() = NotVeryUsefulAspect().apply {
+ // Configure properties of the aspect here
+ }
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.kt
new file mode 100644
index 0000000000..53942988ec
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectj
+
+import org.aspectj.lang.annotation.Aspect
+
+// tag::snippet[]
+@Aspect
+class NotVeryUsefulAspect
+// end::snippet[]
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.kt
new file mode 100644
index 0000000000..3e96153584
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.EnableAspectJAutoProxy
+
+// tag::snippet[]
+@Configuration
+@EnableAspectJAutoProxy
+class ApplicationConfiguration {
+
+ @Bean
+ fun concurrentOperationExecutor() = ConcurrentOperationExecutor().apply {
+ maxRetries = 3
+ order = 100
+ }
+}
+// end::snippet[]
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.kt
new file mode 100644
index 0000000000..c4f918f51f
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample
+
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation.Around
+import org.aspectj.lang.annotation.Aspect
+import org.springframework.core.Ordered
+import org.springframework.dao.PessimisticLockingFailureException
+
+// tag::snippet[]
+@Aspect
+class ConcurrentOperationExecutor : Ordered {
+
+ companion object {
+ private const val DEFAULT_MAX_RETRIES = 2
+ }
+
+ var maxRetries = DEFAULT_MAX_RETRIES
+
+ private var order = 1
+
+ override fun getOrder(): Int {
+ return this.order
+ }
+
+ fun setOrder(order: Int) {
+ this.order = order
+ }
+
+ @Around("com.xyz.CommonPointcuts.businessService()")
+ fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any {
+ var numAttempts = 0
+ var lockFailureException: PessimisticLockingFailureException?
+ do {
+ numAttempts++
+ try {
+ return pjp.proceed()
+ } catch (ex: PessimisticLockingFailureException) {
+ lockFailureException = ex
+ }
+ } while (numAttempts <= this.maxRetries)
+ throw lockFailureException!!
+ }
+} // end::snippet[]
\ No newline at end of file
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.kt
new file mode 100644
index 0000000000..89224a8d48
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample.service
+
+// tag::snippet[]
+@Retention(AnnotationRetention.RUNTIME)
+// marker annotation
+annotation class Idempotent
+// end::snippet[]
\ No newline at end of file
diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.kt b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.kt
new file mode 100644
index 0000000000..da5131d748
--- /dev/null
+++ b/framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2024 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
+ *
+ * https://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.docs.core.aop.ataspectj.aopataspectjexample.service
+
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation.Around
+import org.springframework.stereotype.Service
+
+@Service
+class SampleService {
+
+ // tag::snippet[]
+ @Around("execution(* com.xyz..service.*.*(..)) && " +
+ "@annotation(com.xyz.service.Idempotent)")
+ fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
+ // ...
+ return pjp.proceed(pjp.args)
+ }
+ // end::snippet[]
+
+}
\ No newline at end of file
diff --git a/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.xml b/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.xml
new file mode 100644
index 0000000000..395a8cfe7c
--- /dev/null
+++ b/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.xml b/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.xml
new file mode 100644
index 0000000000..0837f96099
--- /dev/null
+++ b/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.xml b/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.xml
new file mode 100644
index 0000000000..8472b707e5
--- /dev/null
+++ b/framework-docs/src/main/resources/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.xml b/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.xml
new file mode 100644
index 0000000000..736824791b
--- /dev/null
+++ b/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.xml b/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.xml
new file mode 100644
index 0000000000..b591dd381f
--- /dev/null
+++ b/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.xml b/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.xml
new file mode 100644
index 0000000000..b232cce473
--- /dev/null
+++ b/framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file