Skip to content

Commit 515295e

Browse files
committed
Use code includes and tabs in AOP documentation
See gh-22171
1 parent 1455a9f commit 515295e

32 files changed

+762
-363
lines changed

framework-docs/framework-docs.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ dependencies {
6565
api(project(":spring-web"))
6666
api(project(":spring-webmvc"))
6767
api(project(":spring-context-support"))
68+
api(project(":spring-aspects"))
6869

6970
api("org.jetbrains.kotlin:kotlin-stdlib")
7071
api("jakarta.jms:jakarta.jms-api")
@@ -74,6 +75,7 @@ dependencies {
7475
api("com.fasterxml.jackson.core:jackson-databind")
7576
api("com.fasterxml.jackson.module:jackson-module-parameter-names")
7677
api("jakarta.validation:jakarta.validation-api")
78+
api("org.aspectj:aspectjweaver")
7779

7880
implementation(project(":spring-core-test"))
7981
implementation("org.assertj:assertj-core")

framework-docs/modules/ROOT/pages/core/aop/ataspectj/aspectj-support.adoc

Lines changed: 4 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,54 +8,8 @@ determines that a bean is advised by one or more aspects, it automatically gener
88
a proxy for that bean to intercept method invocations and ensures that advice is run
99
as needed.
1010

11-
The @AspectJ support can be enabled with XML- or Java-style configuration. In either
12-
case, you also need to ensure that AspectJ's `aspectjweaver.jar` library is on the
13-
classpath of your application (version 1.9 or later). This library is available in the
14-
`lib` directory of an AspectJ distribution or from the Maven Central repository.
15-
16-
17-
[[aop-enable-aspectj-java]]
18-
== Enabling @AspectJ Support with Java Configuration
19-
20-
To enable @AspectJ support with Java `@Configuration`, add the `@EnableAspectJAutoProxy`
21-
annotation, as the following example shows:
22-
[tabs]
23-
======
24-
Java::
25-
+
26-
[source,java,indent=0,subs="verbatim",role="primary"]
27-
----
28-
@Configuration
29-
@EnableAspectJAutoProxy
30-
public class AppConfig {
31-
}
32-
----
33-
34-
Kotlin::
35-
+
36-
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
37-
----
38-
@Configuration
39-
@EnableAspectJAutoProxy
40-
class AppConfig
41-
----
42-
======
43-
44-
[[aop-enable-aspectj-xml]]
45-
== Enabling @AspectJ Support with XML Configuration
46-
47-
To enable @AspectJ support with XML-based configuration, use the `aop:aspectj-autoproxy`
48-
element, as the following example shows:
49-
50-
[source,xml,indent=0,subs="verbatim"]
51-
----
52-
<aop:aspectj-autoproxy/>
53-
----
54-
55-
This assumes that you use schema support as described in
56-
xref:core/appendix/xsd-schemas.adoc[XML Schema-based configuration].
57-
See xref:core/appendix/xsd-schemas.adoc#aop[the AOP schema] for how to
58-
import the tags in the `aop` namespace.
59-
60-
11+
The @AspectJ support can be enabled with programmatic or XML configuration. In either
12+
case, you also need to ensure that AspectJ's `org.aspectj:aspectjweaver` library is on the
13+
classpath of your application (version 1.9 or later).
6114

15+
include-code::./ApplicationConfiguration[tag=snippet,indent=0]

framework-docs/modules/ROOT/pages/core/aop/ataspectj/at-aspectj.adoc

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,12 @@ minimal steps required for a not-very-useful aspect.
99
The first of the two examples shows a regular bean definition in the application context
1010
that points to a bean class that is annotated with `@Aspect`:
1111

12-
[source,xml,indent=0,subs="verbatim"]
13-
----
14-
<bean id="myAspect" class="com.xyz.NotVeryUsefulAspect">
15-
<!-- configure properties of the aspect here -->
16-
</bean>
17-
----
12+
include-code::./ApplicationConfiguration[tag=snippet,indent=0]
1813

1914
The second of the two examples shows the `NotVeryUsefulAspect` class definition, which is
2015
annotated with `@Aspect`:
2116

22-
[tabs]
23-
======
24-
Java::
25-
+
26-
[source,java,indent=0,subs="verbatim",role="primary",chomp="-packages",fold="none"]
27-
----
28-
package com.xyz;
29-
30-
import org.aspectj.lang.annotation.Aspect;
31-
32-
@Aspect
33-
public class NotVeryUsefulAspect {
34-
}
35-
----
36-
37-
Kotlin::
38-
+
39-
[source,kotlin,indent=0,subs="verbatim",role="secondary",chomp="-packages",fold="none"]
40-
----
41-
package com.xyz
42-
43-
import org.aspectj.lang.annotation.Aspect
44-
45-
@Aspect
46-
class NotVeryUsefulAspect
47-
----
48-
======
17+
include-code::./NotVeryUsefulAspect[tag=snippet,indent=0]
4918

5019
Aspects (classes annotated with `@Aspect`) can have methods and fields, the same as any
5120
other class. They can also contain pointcut, advice, and introduction (inter-type)

framework-docs/modules/ROOT/pages/core/aop/ataspectj/example.adoc

Lines changed: 5 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -16,93 +16,9 @@ aspect.
1616
Because we want to retry the operation, we need to use around advice so that we can
1717
call `proceed` multiple times. The following listing shows the basic aspect implementation:
1818

19-
[tabs]
20-
======
21-
Java::
22-
+
23-
[source,java,indent=0,subs="verbatim",role="primary"]
24-
----
25-
@Aspect
26-
public class ConcurrentOperationExecutor implements Ordered {
19+
include-code::./ConcurrentOperationExecutor[tag=snippet,indent=0]
2720

28-
private static final int DEFAULT_MAX_RETRIES = 2;
29-
30-
private int maxRetries = DEFAULT_MAX_RETRIES;
31-
private int order = 1;
32-
33-
public void setMaxRetries(int maxRetries) {
34-
this.maxRetries = maxRetries;
35-
}
36-
37-
public int getOrder() {
38-
return this.order;
39-
}
40-
41-
public void setOrder(int order) {
42-
this.order = order;
43-
}
44-
45-
@Around("com.xyz.CommonPointcuts.businessService()") // <1>
46-
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
47-
int numAttempts = 0;
48-
PessimisticLockingFailureException lockFailureException;
49-
do {
50-
numAttempts++;
51-
try {
52-
return pjp.proceed();
53-
}
54-
catch(PessimisticLockingFailureException ex) {
55-
lockFailureException = ex;
56-
}
57-
} while(numAttempts <= this.maxRetries);
58-
throw lockFailureException;
59-
}
60-
}
61-
----
62-
<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
63-
64-
Kotlin::
65-
+
66-
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
67-
----
68-
@Aspect
69-
class ConcurrentOperationExecutor : Ordered {
70-
71-
private val DEFAULT_MAX_RETRIES = 2
72-
private var maxRetries = DEFAULT_MAX_RETRIES
73-
private var order = 1
74-
75-
fun setMaxRetries(maxRetries: Int) {
76-
this.maxRetries = maxRetries
77-
}
78-
79-
override fun getOrder(): Int {
80-
return this.order
81-
}
82-
83-
fun setOrder(order: Int) {
84-
this.order = order
85-
}
86-
87-
@Around("com.xyz.CommonPointcuts.businessService()") // <1>
88-
fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
89-
var numAttempts = 0
90-
var lockFailureException: PessimisticLockingFailureException
91-
do {
92-
numAttempts++
93-
try {
94-
return pjp.proceed()
95-
} catch (ex: PessimisticLockingFailureException) {
96-
lockFailureException = ex
97-
}
98-
99-
} while (numAttempts <= this.maxRetries)
100-
throw lockFailureException
101-
}
102-
}
103-
----
104-
<1> References the `businessService` named pointcut defined in xref:core/aop/ataspectj/pointcuts.adoc#aop-common-pointcuts[Sharing Named Pointcut Definitions].
105-
======
21+
`@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].
10622

10723
Note that the aspect implements the `Ordered` interface so that we can set the precedence of
10824
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.
11430

11531
The corresponding Spring configuration follows:
11632

117-
[source,xml,indent=0,subs="verbatim"]
118-
----
119-
<aop:aspectj-autoproxy/>
120-
121-
<bean id="concurrentOperationExecutor"
122-
class="com.xyz.service.impl.ConcurrentOperationExecutor">
123-
<property name="maxRetries" value="3"/>
124-
<property name="order" value="100"/>
125-
</bean>
126-
----
33+
include-code::./ApplicationConfiguration[tag=snippet,indent=0]
12734

12835
To refine the aspect so that it retries only idempotent operations, we might define the following
12936
`Idempotent` annotation:
13037

131-
[tabs]
132-
======
133-
Java::
134-
+
135-
[source,java,indent=0,subs="verbatim",role="primary"]
136-
----
137-
@Retention(RetentionPolicy.RUNTIME)
138-
// marker annotation
139-
public @interface Idempotent {
140-
}
141-
----
142-
143-
Kotlin::
144-
+
145-
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
146-
----
147-
@Retention(AnnotationRetention.RUNTIME)
148-
// marker annotation
149-
annotation class Idempotent
150-
----
151-
======
38+
include-code::./service/Idempotent[tag=snippet,indent=0]
15239

15340
We can then use the annotation to annotate the implementation of service operations. The change
15441
to the aspect to retry only idempotent operations involves refining the pointcut
15542
expression so that only `@Idempotent` operations match, as follows:
15643

157-
[tabs]
158-
======
159-
Java::
160-
+
161-
[source,java,indent=0,subs="verbatim",role="primary"]
162-
----
163-
@Around("execution(* com.xyz..service.*.*(..)) && " +
164-
"@annotation(com.xyz.service.Idempotent)")
165-
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
166-
// ...
167-
}
168-
----
169-
170-
Kotlin::
171-
+
172-
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
173-
----
174-
@Around("execution(* com.xyz..service.*.*(..)) && " +
175-
"@annotation(com.xyz.service.Idempotent)")
176-
fun doConcurrentOperation(pjp: ProceedingJoinPoint): Any? {
177-
// ...
178-
}
179-
----
180-
======
181-
182-
183-
44+
include-code::./service/SampleService[tag=snippet,indent=0]

framework-docs/modules/ROOT/pages/core/aop/ataspectj/introductions.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Kotlin::
7272
+
7373
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
7474
----
75-
val usageTracked = context.getBean("myService", UsageTracked.class)
75+
val usageTracked = context.getBean<UsageTracked>("myService")
7676
----
7777
======
7878

0 commit comments

Comments
 (0)