@@ -888,9 +888,9 @@ that test drives the configuration shown earlier:
888
888
public final class Boot {
889
889
890
890
public static void main(final String[] args) throws Exception {
891
- ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class );
892
- FooService fooService = (FooService) ctx.getBean("fooService" );
893
- fooService.insertFoo (new Foo());
891
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml");
892
+ FooService fooService = ctx.getBean(FooService.class );
893
+ fooService.insertFoo(new Foo());
894
894
}
895
895
}
896
896
----
@@ -1365,18 +1365,22 @@ Consider the following class definition:
1365
1365
@Transactional
1366
1366
public class DefaultFooService implements FooService {
1367
1367
1368
+ @Override
1368
1369
public Foo getFoo(String fooName) {
1369
1370
// ...
1370
1371
}
1371
1372
1373
+ @Override
1372
1374
public Foo getFoo(String fooName, String barName) {
1373
1375
// ...
1374
1376
}
1375
1377
1378
+ @Override
1376
1379
public void insertFoo(Foo foo) {
1377
1380
// ...
1378
1381
}
1379
1382
1383
+ @Override
1380
1384
public void updateFoo(Foo foo) {
1381
1385
// ...
1382
1386
}
@@ -1407,11 +1411,13 @@ Consider the following class definition:
1407
1411
}
1408
1412
----
1409
1413
1410
- Used at the class level as above, the annotation indicates a default for all public methods
1411
- of the declaring class (as well as its subclasses). Alternatively, each method can
1412
- get annotated individually. Note that a class-level annotation does not apply to
1413
- ancestor classes up the class hierarchy; in such a scenario, methods need to be
1414
- locally redeclared in order to participate in a subclass-level annotation.
1414
+ Used at the class level as above, the annotation indicates a default for all methods of
1415
+ the declaring class (as well as its subclasses). Alternatively, each method can be
1416
+ annotated individually. See <<transaction-declarative-annotations-method-visibility>> for
1417
+ further details on which methods Spring considers transactional. Note that a class-level
1418
+ annotation does not apply to ancestor classes up the class hierarchy; in such a scenario,
1419
+ inherited methods need to be locally redeclared in order to participate in a
1420
+ subclass-level annotation.
1415
1421
1416
1422
When a POJO class such as the one above is defined as a bean in a Spring context,
1417
1423
you can make the bean instance transactional through an `@EnableTransactionManagement`
@@ -1441,7 +1447,8 @@ In XML configuration, the `<tx:annotation-driven/>` tag provides similar conveni
1441
1447
<bean id="fooService" class="x.y.service.DefaultFooService"/>
1442
1448
1443
1449
<!-- enable the configuration of transactional behavior based on annotations -->
1444
- <tx:annotation-driven transaction-manager="txManager"/><!-- a TransactionManager is still required --> <1>
1450
+ <!-- a TransactionManager is still required -->
1451
+ <tx:annotation-driven transaction-manager="txManager"/> <1>
1445
1452
1446
1453
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
1447
1454
<!-- (this dependency is defined somewhere else) -->
@@ -1456,7 +1463,7 @@ In XML configuration, the `<tx:annotation-driven/>` tag provides similar conveni
1456
1463
1457
1464
1458
1465
TIP: You can omit the `transaction-manager` attribute in the `<tx:annotation-driven/>`
1459
- tag if the bean name of the `TransactionManager` that you want to wire in has the name,
1466
+ tag if the bean name of the `TransactionManager` that you want to wire in has the name
1460
1467
`transactionManager`. If the `TransactionManager` bean that you want to dependency-inject
1461
1468
has any other name, you have to use the `transaction-manager` attribute, as in the
1462
1469
preceding example.
@@ -1471,18 +1478,22 @@ programming arrangements as the following listing shows:
1471
1478
@Transactional
1472
1479
public class DefaultFooService implements FooService {
1473
1480
1481
+ @Override
1474
1482
public Publisher<Foo> getFoo(String fooName) {
1475
1483
// ...
1476
1484
}
1477
1485
1486
+ @Override
1478
1487
public Mono<Foo> getFoo(String fooName, String barName) {
1479
1488
// ...
1480
1489
}
1481
1490
1491
+ @Override
1482
1492
public Mono<Void> insertFoo(Foo foo) {
1483
1493
// ...
1484
1494
}
1485
1495
1496
+ @Override
1486
1497
public Mono<Void> updateFoo(Foo foo) {
1487
1498
// ...
1488
1499
}
@@ -1518,17 +1529,47 @@ Reactive Streams cancellation signals. See the <<tx-prog-operator-cancel>> secti
1518
1529
"Using the TransactionOperator" for more details.
1519
1530
1520
1531
1532
+ [[transaction-declarative-annotations-method-visibility]]
1521
1533
.Method visibility and `@Transactional`
1522
- ****
1523
- When you use proxies, you should apply the `@Transactional` annotation only to methods
1524
- with public visibility. If you do annotate protected, private or package-visible
1525
- methods with the `@Transactional` annotation, no error is raised, but the annotated
1526
- method does not exhibit the configured transactional settings. If you need to annotate
1527
- non-public methods, consider using AspectJ (described later).
1528
- ****
1534
+ [NOTE]
1535
+ ====
1536
+ When you use transactional proxies with Spring's standard configuration, you should apply
1537
+ the `@Transactional` annotation only to methods with `public` visibility. If you do
1538
+ annotate `protected`, `private`, or package-visible methods with the `@Transactional`
1539
+ annotation, no error is raised, but the annotated method does not exhibit the configured
1540
+ transactional settings. If you need to annotate non-public methods, consider the tip in
1541
+ the following paragraph for class-based proxies or consider using AspectJ compile-time or
1542
+ load-time weaving (described later).
1543
+
1544
+ When using `@EnableTransactionManagement` in a `@Configuration` class, `protected` or
1545
+ package-visible methods can also be made transactional for class-based proxies by
1546
+ registering a custom `transactionAttributeSource` bean like in the following example.
1547
+ Note, however, that transactional methods in interface-based proxies must always be
1548
+ `public` and defined in the proxied interface.
1549
+
1550
+ [source,java,indent=0,subs="verbatim,quotes"]
1551
+ ----
1552
+ /**
1553
+ * Register a custom AnnotationTransactionAttributeSource with the
1554
+ * publicMethodsOnly flag set to false to enable support for
1555
+ * protected and package-private @Transactional methods in
1556
+ * class-based proxies.
1557
+ *
1558
+ * @see ProxyTransactionManagementConfiguration#transactionAttributeSource()
1559
+ */
1560
+ @Bean
1561
+ TransactionAttributeSource transactionAttributeSource() {
1562
+ return new AnnotationTransactionAttributeSource(false);
1563
+ }
1564
+ ----
1565
+
1566
+ The _Spring TestContext Framework_ supports non-private `@Transactional` test methods by
1567
+ default. See <<testing.adoc#testcontext-tx,Transaction Management>> in the testing
1568
+ chapter for examples.
1569
+ ====
1529
1570
1530
1571
You can apply the `@Transactional` annotation to an interface definition, a method
1531
- on an interface, a class definition, or a public method on a class. However, the
1572
+ on an interface, a class definition, or a method on a class. However, the
1532
1573
mere presence of the `@Transactional` annotation is not enough to activate the
1533
1574
transactional behavior. The `@Transactional` annotation is merely metadata that can
1534
1575
be consumed by some runtime infrastructure that is `@Transactional`-aware and that
@@ -1550,12 +1591,13 @@ the proxy are intercepted. This means that self-invocation (in effect, a method
1550
1591
the target object calling another method of the target object) does not lead to an actual
1551
1592
transaction at runtime even if the invoked method is marked with `@Transactional`. Also,
1552
1593
the proxy must be fully initialized to provide the expected behavior, so you should not
1553
- rely on this feature in your initialization code (that is, `@PostConstruct`).
1594
+ rely on this feature in your initialization code -- for example, in a `@PostConstruct`
1595
+ method.
1554
1596
1555
- Consider using of AspectJ mode (see the `mode` attribute in the following table) if you
1556
- expect self-invocations to be wrapped with transactions as well. In this case, there no
1557
- proxy in the first place. Instead, the target class is woven (that is, its byte code is
1558
- modified) to turn `@Transactional` into runtime behavior on any kind of method.
1597
+ Consider using AspectJ mode (see the `mode` attribute in the following table) if you
1598
+ expect self-invocations to be wrapped with transactions as well. In this case, there is
1599
+ no proxy in the first place. Instead, the target class is woven (that is, its byte code
1600
+ is modified) to support `@Transactional` runtime behavior on any kind of method.
1559
1601
1560
1602
[[tx-annotation-driven-settings]]
1561
1603
.Annotation driven transaction settings
@@ -1608,14 +1650,14 @@ NOTE: The `proxy-target-class` attribute controls what type of transactional pro
1608
1650
created for classes annotated with the `@Transactional` annotation. If
1609
1651
`proxy-target-class` is set to `true`, class-based proxies are created. If
1610
1652
`proxy-target-class` is `false` or if the attribute is omitted, standard JDK
1611
- interface-based proxies are created. (See <<core.adoc#aop-proxying>> for a discussion of the
1612
- different proxy types.)
1653
+ interface-based proxies are created. (See <<core.adoc#aop-proxying, Proxying Mechanisms>>
1654
+ for a discussion of the different proxy types.)
1613
1655
1614
- NOTE: `@EnableTransactionManagement` and `<tx:annotation-driven/>` looks for
1656
+ NOTE: `@EnableTransactionManagement` and `<tx:annotation-driven/>` look for
1615
1657
`@Transactional` only on beans in the same application context in which they are defined.
1616
1658
This means that, if you put annotation-driven configuration in a `WebApplicationContext`
1617
1659
for a `DispatcherServlet`, it checks for `@Transactional` beans only in your controllers
1618
- and not your services. See <<web.adoc#mvc-servlet, MVC>> for more information.
1660
+ and not in your services. See <<web.adoc#mvc-servlet, MVC>> for more information.
1619
1661
1620
1662
The most derived location takes precedence when evaluating the transactional settings
1621
1663
for a method. In the case of the following example, the `DefaultFooService` class is
@@ -1663,8 +1705,8 @@ precedence over the transactional settings defined at the class level.
1663
1705
===== `@Transactional` Settings
1664
1706
1665
1707
The `@Transactional` annotation is metadata that specifies that an interface, class,
1666
- or method must have transactional semantics (for example, "` start a brand new read-only
1667
- transaction when this method is invoked, suspending any existing transaction` ").
1708
+ or method must have transactional semantics (for example, "start a brand new read-only
1709
+ transaction when this method is invoked, suspending any existing transaction").
1668
1710
The default `@Transactional` settings are as follows:
1669
1711
1670
1712
* The propagation setting is `PROPAGATION_REQUIRED.`
0 commit comments