From 515295e20555d4c0666cd6ad0426f7cba842fe1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Mon, 8 Apr 2024 16:54:45 +0200 Subject: [PATCH] Use code includes and tabs in AOP documentation See gh-22171 --- framework-docs/framework-docs.gradle | 2 + .../core/aop/ataspectj/aspectj-support.adoc | 54 +------ .../pages/core/aop/ataspectj/at-aspectj.adoc | 35 +--- .../pages/core/aop/ataspectj/example.adoc | 149 +----------------- .../core/aop/ataspectj/introductions.adoc | 2 +- .../ROOT/pages/core/aop/using-aspectj.adoc | 145 ++--------------- .../ApplicationConfiguration.java | 27 ++++ .../CustomWeaverConfiguration.java | 35 ++++ .../ApplicationConfiguration.java | 27 ++++ .../ApplicationConfiguration.java | 27 ++++ .../ApplicationConfiguration.java | 31 ++++ .../aopataspectj/NotVeryUsefulAspect.java | 24 +++ .../ApplicationConfiguration.java | 37 +++++ .../ConcurrentOperationExecutor.java | 63 ++++++++ .../service/Idempotent.java | 27 ++++ .../service/SampleService.java | 36 +++++ .../ApplicationConfiguration.kt | 26 +++ .../CustomWeaverConfiguration.kt | 34 ++++ .../ApplicationConfiguration.kt | 26 +++ .../ApplicationConfiguration.kt | 26 +++ .../aopataspectj/ApplicationConfiguration.kt | 29 ++++ .../aopataspectj/NotVeryUsefulAspect.kt | 23 +++ .../ApplicationConfiguration.kt | 33 ++++ .../ConcurrentOperationExecutor.kt | 59 +++++++ .../aopataspectjexample/service/Idempotent.kt | 23 +++ .../service/SampleService.kt | 35 ++++ .../ApplicationConfiguration.xml | 14 ++ .../CustomWeaverConfiguration.xml | 16 ++ .../ApplicationConfiguration.xml | 14 ++ .../ApplicationConfiguration.xml | 13 ++ .../aopataspectj/ApplicationConfiguration.xml | 13 ++ .../ApplicationConfiguration.xml | 20 +++ 32 files changed, 762 insertions(+), 363 deletions(-) create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.java create mode 100644 framework-docs/src/main/java/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.java create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectj/NotVeryUsefulAspect.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ConcurrentOperationExecutor.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/Idempotent.kt create mode 100644 framework-docs/src/main/kotlin/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/service/SampleService.kt create mode 100644 framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/ApplicationConfiguration.xml create mode 100644 framework-docs/src/main/resources/org/springframework/docs/core/aop/aopajltwspring/CustomWeaverConfiguration.xml create mode 100644 framework-docs/src/main/resources/org/springframework/docs/core/aop/aopatconfigurable/ApplicationConfiguration.xml create mode 100644 framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopaspectjsupport/ApplicationConfiguration.xml create mode 100644 framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectj/ApplicationConfiguration.xml create mode 100644 framework-docs/src/main/resources/org/springframework/docs/core/aop/ataspectj/aopataspectjexample/ApplicationConfiguration.xml 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