Revise transaction annotation recommendations

Closes gh-23538
This commit is contained in:
Juergen Hoeller 2023-10-10 21:56:14 +02:00
parent 8b5d993e61
commit 387a16bd4e
1 changed files with 23 additions and 26 deletions

View File

@ -229,30 +229,27 @@ in the testing chapter for examples.
==== ====
You can apply the `@Transactional` annotation to an interface definition, a method You can apply the `@Transactional` annotation to an interface definition, a method
on an interface, a class definition, or a method on a class. However, the on an interface, a class definition, or a method on a class. However, the mere presence
mere presence of the `@Transactional` annotation is not enough to activate the of the `@Transactional` annotation is not enough to activate the transactional behavior.
transactional behavior. The `@Transactional` annotation is merely metadata that can The `@Transactional` annotation is merely metadata that can be consumed by corresponding
be consumed by some runtime infrastructure that is `@Transactional`-aware and that runtime infrastructure which uses that metadata to configure the appropriate beans with
can use the metadata to configure the appropriate beans with transactional behavior. transactional behavior. In the preceding example, the `<tx:annotation-driven/>` element
In the preceding example, the `<tx:annotation-driven/>` element switches on the switches on actual transaction management at runtime.
transactional behavior.
TIP: The Spring team recommends that you annotate only concrete classes (and methods of TIP: The Spring team recommends that you annotate methods of concrete classes with the
concrete classes) with the `@Transactional` annotation, as opposed to annotating interfaces. `@Transactional` annotation, rather than relying on annotated methods in interfaces,
You certainly can place the `@Transactional` annotation on an interface (or an interface even if the latter does work for interface-based and target-class proxies as of 5.0.
method), but this works only as you would expect it to if you use interface-based Since Java annotations are not inherited from interfaces, interface-declared annotations
proxies. The fact that Java annotations are not inherited from interfaces means that, are still not recognized by the weaving infrastructure when using AspectJ mode, so the
if you use class-based proxies (`proxy-target-class="true"`) or the weaving-based aspect does not get applied. As a consequence, your transaction annotations may be
aspect (`mode="aspectj"`), the transaction settings are not recognized by the proxying silently ignored: Your code might appear to "work" until you test a rollback scenario.
and weaving infrastructure, and the object is not wrapped in a transactional proxy.
NOTE: In proxy mode (which is the default), only external method calls coming in through NOTE: In proxy mode (which is the default), only external method calls coming in through
the proxy are intercepted. This means that self-invocation (in effect, a method within the proxy are intercepted. This means that self-invocation (in effect, a method within
the target object calling another method of the target object) does not lead to an actual the target object calling another method of the target object) does not lead to an actual
transaction at runtime even if the invoked method is marked with `@Transactional`. Also, transaction at runtime even if the invoked method is marked with `@Transactional`. Also,
the proxy must be fully initialized to provide the expected behavior, so you should not the proxy must be fully initialized to provide the expected behavior, so you should not
rely on this feature in your initialization code -- for example, in a `@PostConstruct` rely on this feature in your initialization code -- e.g. in a `@PostConstruct` method.
method.
Consider using AspectJ mode (see the `mode` attribute in the following table) if you Consider using AspectJ mode (see the `mode` attribute in the following table) if you
expect self-invocations to be wrapped with transactions as well. In this case, there is expect self-invocations to be wrapped with transactions as well. In this case, there is
@ -277,20 +274,20 @@ is modified) to support `@Transactional` runtime behavior on any kind of method.
framework (following proxy semantics, as discussed earlier, applying to method calls framework (following proxy semantics, as discussed earlier, applying to method calls
coming in through the proxy only). The alternative mode (`aspectj`) instead weaves the coming in through the proxy only). The alternative mode (`aspectj`) instead weaves the
affected classes with Spring's AspectJ transaction aspect, modifying the target class affected classes with Spring's AspectJ transaction aspect, modifying the target class
byte code to apply to any kind of method call. AspectJ weaving requires byte code to apply to any kind of method call. AspectJ weaving requires `spring-aspects.jar`
`spring-aspects.jar` in the classpath as well as having load-time weaving (or compile-time in the classpath as well as having load-time weaving (or compile-time weaving) enabled.
weaving) enabled. (See xref:core/aop/using-aspectj.adoc#aop-aj-ltw-spring[Spring configuration] (See xref:core/aop/using-aspectj.adoc#aop-aj-ltw-spring[Spring configuration] for details
for details on how to set up load-time weaving.) on how to set up load-time weaving.)
| `proxy-target-class` | `proxy-target-class`
| `proxyTargetClass` | `proxyTargetClass`
| `false` | `false`
| Applies to `proxy` mode only. Controls what type of transactional proxies are created | Applies to `proxy` mode only. Controls what type of transactional proxies are created
for classes annotated with the `@Transactional` annotation. If the for classes annotated with the `@Transactional` annotation. If the `proxy-target-class`
`proxy-target-class` attribute is set to `true`, class-based proxies are created. attribute is set to `true`, class-based proxies are created. If `proxy-target-class` is
If `proxy-target-class` is `false` or if the attribute is omitted, then standard JDK `false` or if the attribute is omitted, then standard JDK interface-based proxies are
interface-based proxies are created. (See xref:core/aop/proxying.adoc[Proxying Mechanisms] created. (See xref:core/aop/proxying.adoc[Proxying Mechanisms] for a detailed examination
for a detailed examination of the different proxy types.) of the different proxy types.)
| `order` | `order`
| `order` | `order`