Oh, heute ist Heiligabend ~: santa :: snowflake: Machen Sie sich darüber keine Sorgen ... Dieses Mal zeige ich Ihnen, wie Sie Transaktionen in Spring Boot steuern können, ohne "@ Transactional" (annotationsgesteuertes Transaktionsmanagement) zu verwenden.
Einige Leute denken vielleicht, dass Sie "@ Transactional" verwenden sollten, aber da Sie "@ Transaction" nur für die von Ihnen erstellten Komponenten angeben können, hängt die OSS-Bibliothek des Drittanbieters nicht von Spring ab. Es ist nicht möglich, eine Transaktion auf eine Methode wie (offensichtlich ...: heat_smile :) anzuwenden.
Zusätzlich zu der Methode zur Verwendung von Anmerkungen zur Angabe der im Frühjahr zu handelnden Methode
Methoden etc. werden unterstützt.
Wenn Sie Spring schon lange verwenden, wurde in der Bean-Definition mit XML möglicherweise die folgende Transaktionssteuerungsdeklaration angezeigt. In diesem Beispiel unterliegen alle öffentlichen Methoden der Klasse "TxDemoApplication" der Transaktionssteuerung.
src/resources/transactionContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">
<tx:advice id="transactionAdvisor">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txDemoApplicationPointcut" expression="execution(* com.example.TxDemoApplication.*(..))"/>
<aop:advisor advice-ref="transactionAdvisor" pointcut-ref="txDemoApplicationPointcut"/>
</aop:config>
</beans>
Selbst beim Spring Boot funktioniert es, wenn Sie eine XML-Datei wie ↑ erstellen und wie unten gezeigt mit @ ImportResource
laden.
@SpringBootApplication
@ImportResource("classpath:/transactionContext.xml")
public class TxDemoApplication implements CommandLineRunner {
// ...
}
Aber ... ich möchte nicht mehr zur XML-Datei zurückkehren ...: heat_smile: Wenn Sie Spring from Spring Boot verwenden (diejenigen, die nur Java Config kennen), frage ich mich, wie man Beans mit XML ~ definiert Daher gibt es einige Leute: zwinker:
Wenn Sie dasselbe mit Java Config ausdrücken möchten ... Erstellen Sie einfach die folgende Java Config.
@Configuration
public class TransactionConfig {
@Bean
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
PlatformTransactionManager transactionManager) {
//Geben Sie die Methode zum Verwalten von Transaktionen und die für die Transaktionssteuerung erforderlichen Attributwerte an.
MethodMapTransactionAttributeSource source = new MethodMapTransactionAttributeSource();
source.addTransactionalMethod(TxDemoApplication.class, "*", new RuleBasedTransactionAttribute());
//Generieren Sie einen AOP Advisor, der Transaktionen steuert
//Beratung zur Transaktionskontrolle(TransactionInteceptor)Der Punktschnitt, der den Anwendungsort von angibt, ist mit der in ↑ angegebenen Methode verknüpft.
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(source);
advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
return advisor;
}
}
Note:
Wenn Sie diesen Mechanismus verwenden möchten, benötigen Sie die JAR von "org.aspectj: aspectjweaver" im Klassenpfad. Fügen Sie also "org.springframework.boot: spring-boot-Starter-aop" als abhängige Bibliothek hinzu. ..
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
Warning:
Mit Spring Boot ermöglicht der automatische Konfigurationsmechanismus auch die Steuerung von Transaktionen mithilfe von "@ Transactional" (annotationsgesteuertes Transaktionsmanagement). Daher ... Wenn der in Java Config in ↑ angegebenen Methode "@ Transactional" hinzugefügt wird, wird der Hinweis ("TransactionInteceptor") zur Transaktionssteuerung zweimal angewendet. Seien Sie also vorsichtig.
Im obigen Beispiel wird "MethodMapTransactionAttributeSource" verwendet, Spring bietet jedoch einige Implementierungsklassen für "TransactionAttributeSource".
Name der Klasse | Erläuterung |
---|---|
NameMatchTransactionAttributeSource |
Wenden Sie die Transaktionssteuerung auf Methoden an, die dem angegebenen Methodennamen (Muster) entsprechen. |
MethodMapTransactionAttributeSource |
Wenden Sie die Transaktionssteuerung auf den angegebenen Methodennamen (Muster) der angegebenen Klasse an |
MatchAlwaysTransactionAttributeSource |
Wenden Sie die Transaktionssteuerung auf alle Methoden an |
AnnotationTransactionAttributeSource |
Wenden Sie die Transaktionssteuerung auf mit Spring, JTA und EJB kommentierte Klassenmethoden an (diese Klasse wird bei der automatischen Konfiguration von Spring Boot verwendet). |
CompositeTransactionAttributeSource |
Plural-TransactionAttributeSource Transaktionssteuerung aggregieren und anwenden |
Mit BeanFactoryTransactionAttributeSourceAdvisor können Sie die Klassen filtern, für die AOP gilt. Beispiel: Wenn Sie nur Beans anwenden möchten, denen "@ Service" zugewiesen ist, können Sie die folgenden Beans definieren.
@Configuration
public class TransactionConfig {
@Bean
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
PlatformTransactionManager transactionManager) {
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.addTransactionalMethod("*", new RuleBasedTransactionAttribute());
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(source);
advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
advisor.setClassFilter(clazz -> AnnotationUtils.findAnnotation(clazz, Service.class) != null); //Implementieren Sie Filterbedingungen und`setClassFilter`Anruf
return advisor;
}
}
Unten finden Sie eine Beispielanwendung, die zur Überprüfung des Betriebs erstellt wurde.
Laden Sie das Projekt herunter, indem Sie "JDBC", "H2" und "AOP" als abhängige Bibliotheken für "SPRING INITIALIZR" auswählen.
Stellen Sie den Spring JDBC-Protokollausgabemodus auf Debuggen ein, um festzustellen, ob die Transaktion angewendet wurde.
src/resources/application.properties
logging.level.org.springframework.jdbc=debug
Implementieren Sie als Nächstes "CommandRunner" in der Spring Boot-Anwendung und definieren Sie die Bean für die Transaktionssteuerung.
package com.example;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
import org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
@SpringBootApplication
public class TxDemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(TxDemoApplication.class, args);
}
private final JdbcOperations jdbcOperations;
public TxDemoApplication(JdbcOperations jdbcOperations) {
this.jdbcOperations = jdbcOperations;
}
@Override //Diese Methode unterliegt der Transaktionskontrolle, aber ...@Transaktion wird nicht gewährt! !!
public void run(String... args) throws Exception {
Integer value = jdbcOperations.queryForObject("SELECT 1", Integer.class);
System.out.println(value);
}
@Configuration
static class TransactionConfig {
@Bean
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
PlatformTransactionManager transactionManager) {
MethodMapTransactionAttributeSource source = new MethodMapTransactionAttributeSource();
source.addTransactionalMethod(TxDemoApplication.class, "*", new RuleBasedTransactionAttribute());
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(source);
advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
return advisor;
}
}
}
Lassen Sie uns nun die Spring Boot-Anwendung ausführen.
$ ./mvnw spring-boot:run
...
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.4.3.RELEASE)
2016-12-24 16:20:30.713 INFO 58327 --- [ main] com.example.TxDemoApplication : Starting TxDemoApplication on Kazuki-no-MacBook-Pro.local with PID 58327 (/Users/shimizukazuki/Downloads/tx-demo/target/classes started by shimizukazuki in /Users/shimizukazuki/Downloads/tx-demo)
2016-12-24 16:20:30.715 INFO 58327 --- [ main] com.example.TxDemoApplication : No active profile set, falling back to default profiles: default
2016-12-24 16:20:30.748 INFO 58327 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1e2e2b3: startup date [Sat Dec 24 16:20:30 JST 2016]; root of context hierarchy
2016-12-24 16:20:31.454 INFO 58327 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2016-12-24 16:20:31.469 DEBUG 58327 --- [ main] o.s.j.d.DataSourceTransactionManager : Creating new transaction with name [com.example.TxDemoApplication$$EnhancerBySpringCGLIB$$9f83f17d.run]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2016-12-24 16:20:31.609 DEBUG 58327 --- [ main] o.s.j.d.DataSourceTransactionManager : Acquired Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]] for JDBC transaction
2016-12-24 16:20:31.611 DEBUG 58327 --- [ main] o.s.j.d.DataSourceTransactionManager : Switching JDBC Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]] to manual commit
2016-12-24 16:20:31.618 DEBUG 58327 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing SQL query [SELECT 1]
1
2016-12-24 16:20:31.638 DEBUG 58327 --- [ main] o.s.j.d.DataSourceTransactionManager : Initiating transaction commit
2016-12-24 16:20:31.638 DEBUG 58327 --- [ main] o.s.j.d.DataSourceTransactionManager : Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]]
2016-12-24 16:20:31.639 DEBUG 58327 --- [ main] o.s.j.d.DataSourceTransactionManager : Releasing JDBC Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]] after transaction
2016-12-24 16:20:31.639 DEBUG 58327 --- [ main] o.s.jdbc.datasource.DataSourceUtils : Returning JDBC Connection to DataSource
2016-12-24 16:20:31.642 INFO 58327 --- [ main] com.example.TxDemoApplication : Started TxDemoApplication in 1.106 seconds (JVM running for 3.466)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.612 s
[INFO] Finished at: 2016-12-24T16:20:31+09:00
[INFO] Final Memory: 24M/315M
[INFO] ------------------------------------------------------------------------
2016-12-24 16:20:31.742 INFO 58327 --- [ Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@1e2e2b3: startup date [Sat Dec 24 16:20:30 JST 2016]; root of context hierarchy
2016-12-24 16:20:31.744 INFO 58327 --- [ Thread-1] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
Wenn Sie sich das Konsolenprotokoll ansehen, sehen Sie, dass die Transaktion vor und nach der Implementierung von SQL gestartet, festgeschrieben und beendet wird: clap :: clap :: clap:
Es wird möglicherweise nicht oft verwendet, aber ... Sie können Transaktionen für Methoden steuern, die nicht über "@ Transactional" verfügen. Grundsätzlich denke ich, dass es besser ist, "@ Transactional" hinzuzufügen, um Transaktionen für die von Ihnen erstellten Komponenten zu steuern. Abhängig von den Anforderungen der Anwendung kann die diesmal eingeführte Methode in einigen Fällen jedoch effektiv sein. Hmm.
Happy Christmas 2016 !! :wave:
Recommended Posts