@@ -837,9 +837,9 @@ that test drives the configuration shown earlier:
837
837
public final class Boot {
838
838
839
839
public static void main(final String[] args) throws Exception {
840
- ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class );
841
- FooService fooService = (FooService) ctx.getBean("fooService" );
842
- fooService.insertFoo (new Foo());
840
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml");
841
+ FooService fooService = ctx.getBean(FooService.class );
842
+ fooService.insertFoo(new Foo());
843
843
}
844
844
}
845
845
----
@@ -1314,18 +1314,22 @@ Consider the following class definition:
1314
1314
@Transactional
1315
1315
public class DefaultFooService implements FooService {
1316
1316
1317
+ @Override
1317
1318
public Foo getFoo(String fooName) {
1318
1319
// ...
1319
1320
}
1320
1321
1322
+ @Override
1321
1323
public Foo getFoo(String fooName, String barName) {
1322
1324
// ...
1323
1325
}
1324
1326
1327
+ @Override
1325
1328
public void insertFoo(Foo foo) {
1326
1329
// ...
1327
1330
}
1328
1331
1332
+ @Override
1329
1333
public void updateFoo(Foo foo) {
1330
1334
// ...
1331
1335
}
@@ -1356,11 +1360,13 @@ Consider the following class definition:
1356
1360
}
1357
1361
----
1358
1362
1359
- Used at the class level as above, the annotation indicates a default for all public methods
1360
- of the declaring class (as well as its subclasses). Alternatively, each method can
1361
- get annotated individually. Note that a class-level annotation does not apply to
1362
- ancestor classes up the class hierarchy; in such a scenario, methods need to be
1363
- locally redeclared in order to participate in a subclass-level annotation.
1363
+ Used at the class level as above, the annotation indicates a default for all methods of
1364
+ the declaring class (as well as its subclasses). Alternatively, each method can be
1365
+ annotated individually. See <<transaction-declarative-annotations-method-visibility>> for
1366
+ further details on which methods Spring considers transactional. Note that a class-level
1367
+ annotation does not apply to ancestor classes up the class hierarchy; in such a scenario,
1368
+ inherited methods need to be locally redeclared in order to participate in a
1369
+ subclass-level annotation.
1364
1370
1365
1371
When a POJO class such as the one above is defined as a bean in a Spring context,
1366
1372
you can make the bean instance transactional through an `@EnableTransactionManagement`
@@ -1390,7 +1396,8 @@ In XML configuration, the `<tx:annotation-driven/>` tag provides similar conveni
1390
1396
<bean id="fooService" class="x.y.service.DefaultFooService"/>
1391
1397
1392
1398
<!-- enable the configuration of transactional behavior based on annotations -->
1393
- <tx:annotation-driven transaction-manager="txManager"/><!-- a TransactionManager is still required --> <1>
1399
+ <!-- a TransactionManager is still required -->
1400
+ <tx:annotation-driven transaction-manager="txManager"/> <1>
1394
1401
1395
1402
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
1396
1403
<!-- (this dependency is defined somewhere else) -->
@@ -1405,7 +1412,7 @@ In XML configuration, the `<tx:annotation-driven/>` tag provides similar conveni
1405
1412
1406
1413
1407
1414
TIP: You can omit the `transaction-manager` attribute in the `<tx:annotation-driven/>`
1408
- tag if the bean name of the `TransactionManager` that you want to wire in has the name,
1415
+ tag if the bean name of the `TransactionManager` that you want to wire in has the name
1409
1416
`transactionManager`. If the `TransactionManager` bean that you want to dependency-inject
1410
1417
has any other name, you have to use the `transaction-manager` attribute, as in the
1411
1418
preceding example.
@@ -1420,18 +1427,22 @@ programming arrangements as the following listing shows:
1420
1427
@Transactional
1421
1428
public class DefaultFooService implements FooService {
1422
1429
1430
+ @Override
1423
1431
public Publisher<Foo> getFoo(String fooName) {
1424
1432
// ...
1425
1433
}
1426
1434
1435
+ @Override
1427
1436
public Mono<Foo> getFoo(String fooName, String barName) {
1428
1437
// ...
1429
1438
}
1430
1439
1440
+ @Override
1431
1441
public Mono<Void> insertFoo(Foo foo) {
1432
1442
// ...
1433
1443
}
1434
1444
1445
+ @Override
1435
1446
public Mono<Void> updateFoo(Foo foo) {
1436
1447
// ...
1437
1448
}
@@ -1467,17 +1478,47 @@ Reactive Streams cancellation signals. See the <<tx-prog-operator-cancel>> secti
1467
1478
"Using the TransactionOperator" for more details.
1468
1479
1469
1480
1481
+ [[transaction-declarative-annotations-method-visibility]]
1470
1482
.Method visibility and `@Transactional`
1471
- ****
1472
- When you use proxies, you should apply the `@Transactional` annotation only to methods
1473
- with public visibility. If you do annotate protected, private or package-visible
1474
- methods with the `@Transactional` annotation, no error is raised, but the annotated
1475
- method does not exhibit the configured transactional settings. If you need to annotate
1476
- non-public methods, consider using AspectJ (described later).
1477
- ****
1483
+ [NOTE]
1484
+ ====
1485
+ When you use transactional proxies with Spring's standard configuration, you should apply
1486
+ the `@Transactional` annotation only to methods with `public` visibility. If you do
1487
+ annotate `protected`, `private`, or package-visible methods with the `@Transactional`
1488
+ annotation, no error is raised, but the annotated method does not exhibit the configured
1489
+ transactional settings. If you need to annotate non-public methods, consider the tip in
1490
+ the following paragraph for class-based proxies or consider using AspectJ compile-time or
1491
+ load-time weaving (described later).
1492
+
1493
+ When using `@EnableTransactionManagement` in a `@Configuration` class, `protected` or
1494
+ package-visible methods can also be made transactional for class-based proxies by
1495
+ registering a custom `transactionAttributeSource` bean like in the following example.
1496
+ Note, however, that transactional methods in interface-based proxies must always be
1497
+ `public` and defined in the proxied interface.
1498
+
1499
+ [source,java,indent=0,subs="verbatim,quotes"]
1500
+ ----
1501
+ /**
1502
+ * Register a custom AnnotationTransactionAttributeSource with the
1503
+ * publicMethodsOnly flag set to false to enable support for
1504
+ * protected and package-private @Transactional methods in
1505
+ * class-based proxies.
1506
+ *
1507
+ * @see ProxyTransactionManagementConfiguration#transactionAttributeSource()
1508
+ */
1509
+ @Bean
1510
+ TransactionAttributeSource transactionAttributeSource() {
1511
+ return new AnnotationTransactionAttributeSource(false);
1512
+ }
1513
+ ----
1514
+
1515
+ The _Spring TestContext Framework_ supports non-private `@Transactional` test methods by
1516
+ default. See <<testing.adoc#testcontext-tx,Transaction Management>> in the testing
1517
+ chapter for examples.
1518
+ ====
1478
1519
1479
1520
You can apply the `@Transactional` annotation to an interface definition, a method
1480
- on an interface, a class definition, or a public method on a class. However, the
1521
+ on an interface, a class definition, or a method on a class. However, the
1481
1522
mere presence of the `@Transactional` annotation is not enough to activate the
1482
1523
transactional behavior. The `@Transactional` annotation is merely metadata that can
1483
1524
be consumed by some runtime infrastructure that is `@Transactional`-aware and that
@@ -1499,12 +1540,13 @@ the proxy are intercepted. This means that self-invocation (in effect, a method
1499
1540
the target object calling another method of the target object) does not lead to an actual
1500
1541
transaction at runtime even if the invoked method is marked with `@Transactional`. Also,
1501
1542
the proxy must be fully initialized to provide the expected behavior, so you should not
1502
- rely on this feature in your initialization code (that is, `@PostConstruct`).
1543
+ rely on this feature in your initialization code -- for example, in a `@PostConstruct`
1544
+ method.
1503
1545
1504
- Consider using of AspectJ mode (see the `mode` attribute in the following table) if you
1505
- expect self-invocations to be wrapped with transactions as well. In this case, there no
1506
- proxy in the first place. Instead, the target class is woven (that is, its byte code is
1507
- modified) to turn `@Transactional` into runtime behavior on any kind of method.
1546
+ Consider using AspectJ mode (see the `mode` attribute in the following table) if you
1547
+ expect self-invocations to be wrapped with transactions as well. In this case, there is
1548
+ no proxy in the first place. Instead, the target class is woven (that is, its byte code
1549
+ is modified) to support `@Transactional` runtime behavior on any kind of method.
1508
1550
1509
1551
[[tx-annotation-driven-settings]]
1510
1552
.Annotation driven transaction settings
@@ -1557,14 +1599,14 @@ NOTE: The `proxy-target-class` attribute controls what type of transactional pro
1557
1599
created for classes annotated with the `@Transactional` annotation. If
1558
1600
`proxy-target-class` is set to `true`, class-based proxies are created. If
1559
1601
`proxy-target-class` is `false` or if the attribute is omitted, standard JDK
1560
- interface-based proxies are created. (See <<core.adoc#aop-proxying>> for a discussion of the
1561
- different proxy types.)
1602
+ interface-based proxies are created. (See <<core.adoc#aop-proxying, Proxying Mechanisms>>
1603
+ for a discussion of the different proxy types.)
1562
1604
1563
- NOTE: `@EnableTransactionManagement` and `<tx:annotation-driven/>` looks for
1605
+ NOTE: `@EnableTransactionManagement` and `<tx:annotation-driven/>` look for
1564
1606
`@Transactional` only on beans in the same application context in which they are defined.
1565
1607
This means that, if you put annotation-driven configuration in a `WebApplicationContext`
1566
1608
for a `DispatcherServlet`, it checks for `@Transactional` beans only in your controllers
1567
- and not your services. See <<web.adoc#mvc-servlet, MVC>> for more information.
1609
+ and not in your services. See <<web.adoc#mvc-servlet, MVC>> for more information.
1568
1610
1569
1611
The most derived location takes precedence when evaluating the transactional settings
1570
1612
for a method. In the case of the following example, the `DefaultFooService` class is
@@ -1612,8 +1654,8 @@ precedence over the transactional settings defined at the class level.
1612
1654
===== `@Transactional` Settings
1613
1655
1614
1656
The `@Transactional` annotation is metadata that specifies that an interface, class,
1615
- or method must have transactional semantics (for example, "` start a brand new read-only
1616
- transaction when this method is invoked, suspending any existing transaction` ").
1657
+ or method must have transactional semantics (for example, "start a brand new read-only
1658
+ transaction when this method is invoked, suspending any existing transaction").
1617
1659
The default `@Transactional` settings are as follows:
1618
1660
1619
1661
* The propagation setting is `PROPAGATION_REQUIRED.`
0 commit comments