This article is based on the 3.0+ version only as a test) assuming that the spring container defines two transaction managers: Transactionmanagerx,transactionmanagery, which is in charge of two data sources Datasourcex and Datasourcey.
<transaction-manager= "Transactionmanagerx"/>< transaction-manager= "Transactionmanagery"/>
(The order of definition in the spring container is as above) has the following application code:
Public Interface Testentityservice {publicvoid methodx (); Public void methody ();}
Interface Implementation Class 1
Public class Implements Testentityservice {@Resourceprivate Testentitydao Testentitydao; // The actual operation is Datasourcex. @Transactional Public void Methodx () {testentitydao.xxx (); testentitydao.zzz ();} Public void methody () {}}
Interface Implementation Class 2
public class Anothertestentityserviceimpl implements Testentityservice {@Resource private Testentitydao Anothertestentitydao; // @Transactional public void Methodx () {testentitydao.mmm (); testentitydao.nnn ();} public void Methody () {}}
Assuming that the method METHODX requires transaction control, we usually add the @transactional annotation directly to the method, but it seems that the transactional callout before spring3.0 (the specific version is not clear) does not support distinguishing which transaction manager to use. Version transactional after 3.0 adds a string type of Value property to be distinguished by a special designation. For example, @transactional ("AAAAA"), which is displayed, requires spring to manage transactions with a id= "AAAAA" transaction manager. This property can also be omitted (omitted by default in the container TransactionManager) for the use of this property to do the following test to
METHODX () transaction Effective test results |
@Transactional ("Transactionmanagerx") |
@Transactional ("Transactionmanagery") |
@Transactional ("Transactionmanagerz") Transactionmanagerz for undefined |
@Transactional |
Testentityserviceimpl (actual use of Datasourcex) |
Y |
N |
Y |
Y |
Anothertestentityserviceimpl (actual use of Datasourcey) |
N |
Y |
N |
N |
If you change the order in which two transaction managers are defined in a container, such as
<transaction-manager= "Transactionmanagery"/>< transaction-manager= "Transactionmanagerx"/>
The results obtained
METHODX () transaction Effective test results |
@Transactional ("Transactionmanagerx") |
@Transactional ("Transactionmanagery") |
@Transactional ("Transactionmanagerz") Transactionmanagerz for undefined |
@Transactional |
Testentityserviceimpl (actual use of Datasourcex) |
Y |
N |
N |
N |
Anothertestentityserviceimpl (actual use of Datasourcey) |
N |
Y |
Y |
Y |
Analysis results (in fact the source can be reflected): container specifies a default transaction manager
1. Transaction control is normal when the transaction manager that needs to be used is correctly specified in @transactional ("xxx"). 2. If @transactional specifies a transaction manager that is not defined, spring is handled by default transaction manager. (If the program is using the same data source as the default transaction manager, the transaction control will take effect). 3. If @transactional does not specify a transaction manager, use the default. 4. If the @transactional specifies a mismatched transaction manager (the data source that is actually used is inconsistent with the data source that is controlled by the specified transaction manager), the transaction control is invalidated. Note: Spring container default transaction manager: In the load order, first loaded as default. For example, if <tx:annotation-driven transaction-manager= "Transactionmanagerx"/><tx:annotation-driven Transaction-manager= the "transactionmanagery"/> is defined in the same file, the first Transactionmanagerx as the default. defined in different files, then by the load order of the files, first loaded as default.
Recommendation: When @transactional is needed in the actual code, even if there is only one transactionmanager by default, @Transactional will also indicate it. In order to improve the readability of the code after the new data source, in addition to prevent the definition of multiple data sources, the previous default is not by spring defaults to default (such as the day on the line to define a new data source, just the new definition of the TransactionManager is loaded first, it is tragic. )
Two. Bean configuration using the container with <tx:annotation-driven > (need to add some XSD), requires transaction control of the service, do not need to do other specific bean configuration, such as the agent wrapper. Direct configuration can
<id= "Testentityservice" class= " Com.xxx.impl.TestEntityServiceImpl "/>
Spring will be used by the jdkdynamicaopproxy generated by the proxy class. The effect of this usage is the same as that used in the configuration below. are provided by the Jdkdynamicaopproxy build proxy object. I think the difference is that the following method is not good for code readability in transaction control, because which method requires transaction control and control granularity is in the configuration file, and the code is separated.
<BeanID= "TestEntityService3"class= "Org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> < Propertyname= "TransactionManager"ref= "Transactionmanagerx" /> < Propertyname= "Target"> <Beanclass= "Com.xxxx.impl.TestEntityServiceImpl" /> </ Property> < Propertyname= "Proxyinterfaces"value= "Com.xxxx.TestEntityService"/> < Propertyname= "Transactionattributes"> <Props> <propKey="*">Propagation_required</prop> </Props> </ Property></Bean>
The visibility and @Transactional of the method @transactional annotations should only be applied to the public visibility method. If you use @Transactional annotations on protected, private, or package-visible methods, it will not error, but this annotated method will not show the configured transaction settings. @Transactional annotations can be applied to interface definitions and interface methods, class definitions, and public methods of classes. Note, however, that only @Transactional annotations appear to be less than the open transaction behavior, which is only a meta-data that can be used to identify @Transactional annotations and the beans that are configured appropriately to have transactional behavior. In the above example, it is actually the presence of the <tx:annotation-driven/> element that opens the transaction behavior. The spring team's recommendation is that you use @Transactional annotations on specific classes (or methods of classes) rather than on any interface that the class implements. You can certainly use @Transactional annotations on the interface, but this will only take effect if you set up an interface-based proxy. Because annotations are not inherited. In actual development, it is most likely to prefer to extract the persisted operation's code into another method (because the business code that does not want the transaction to be extended too long), and then add @transactional to the extracted method, the result is that the extracted code, even if the transaction tag is added, There is also no effect on transaction control (both private and public). For example:
Public class Implements Testentityservice {@Resourceprivate Testentitydao Testentitydao; // The actual operation is Datasourcex. @Transactional Public void Methodx () {testentitydao.xxx (); testentitydao.zzz ();} Public void Methody () {Methodx ()}}
If Testentityservice.methody () is executed, the transaction does not take effect. Only Testentityservice.methody () is effective. From the principles of spring implementation (dynamic proxies and AOP), only external calls are intercepted, and internal calls to methods are usually not supported by AOP. From the Internet to an article, you can solve the problem. Http://blog.csdn.net/quzishen/archive/2010/08/11/5803721.aspx
Spring's Annotation-driven configuration transaction manager detailed