Control de transacciones declarativo basado en AOP

1. Descripción general de la programación de transacciones de Spring

La transacción es algo indispensable en el desarrollo. Cuando usamos el desarrollo JDBC, usamos la conexión para controlar las transacciones. Cuando usamos MyBatis, usamos SqlSession para controlar las transacciones. Las desventajas son obvias. Cuando cambiamos las tecnologías de acceso a la base de datos, la forma de control de las transacciones siempre cambiará. Spring proporciona una interfaz para el control unificado de las transacciones basadas en estas tecnologías. Las transacciones de Spring se dividen en: control de transacción programático y control de transacción declarativo.

inserte la descripción de la imagen aquí

Hay tres clases principales relacionadas con la programación de transacciones de Spring:

inserte la descripción de la imagen aquí

Aunque no aprendemos el control programático de transacciones, necesitamos entender las clases correspondientes al control programático de transacciones, porque también veremos la sombra de estas clases cuando realizamos el control declarativo de transacciones a través de la configuración.

2. Cree un entorno de prueba

Para crear un entorno de transferencia, la capa dao tiene un método para transferir dinero, un método para transferir dinero, y la capa de servicio tiene un método para transferir dinero, y el método para transferir dinero y transferir dinero en la capa dao es llama internamente. El trabajo de preparación es el siguiente: ⚫
Base de datos Prepara una tabla de cuentas tb_account;
⚫ La capa Dao prepara un AccountMapper, que incluye dos métodos de incrMoney y decrMoney;
⚫ La capa de servicio prepara un método transferMoney, que llama a los métodos incrMoney y decrMoney respectivamente;
⚫ Realice la configuración de administración de Bean en el archivo applicationContext;
⚫ La prueba es Transferencias normales y transferencias anormales.

3. Control de transacciones declarativo basado en XML

Combinando la tecnología AOP que aprendimos anteriormente, es fácil imaginar que AOP se puede usar para mejorar la transacción del método de Servicio.
⚫ Clase de destino: AccountServiceImpl
⚫ Corte de punto: todos los métodos de negocio en la clase de negocio de servicio
⚫ Clase de notificación: proporcionado por Spring, el método de notificación ha sido definido, solo necesita configurar

Analizamos:
⚫ Spring proporciona la clase de notificación y es necesario importar las coordenadas relevantes de la transacción de Spring;
⚫ Configurar la clase de destino AccountServiceImpl;
⚫ Usar la etiqueta de asesor para configurar el aspecto.

Importe las coordenadas relevantes de las transacciones Spring, las coordenadas spring-jdbc han introducido las coordenadas spring-tx

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
	<version>5.2.13.RELEASE</version>
</dependency>

inserte la descripción de la imagen aquí

Configurar la clase de destino AccountServiceImpl

<bean id="accountService" class="com.itheima.service.impl.AccoutServiceImpl">
	<property name="accountMapper" ref="accountMapper"></property>
</bean>

Configurar aspectos usando la etiqueta de asesor

<aop:config>
	<aop:advisor advice-ref="Spring提供的通知类" pointcut="execution(* com.itheima.service.impl.*.*(..))"/>
</aop:config>

Pregunta: ¿Quién es la clase de notificación proporcionada por Spring? Lo proporciona la configuración de la etiqueta de aviso en el paquete spring-tx

xmlns:tx="http://www.springframework.org/schema/tx" 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/springtx.xsd

<!--Spring提供的事务通知-->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="transferMoney"/>
	</tx:attributes>
</tx:advice>

<!--平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

<aop:config>
	<aop:advisor advice-ref="myAdvice" pointcut="execution(* com.itheima.service.impl.*.*(..))"/>
</aop:config>

Expliquemos la configuración anterior en detalle:

En primer lugar, el administrador de transacciones de la plataforma PlatformTransactionManager es una interfaz estándar proporcionada por Spring para encapsular la operación específica de la transacción y encapsula los métodos de compromiso y reversión de la transacción.

public interface PlatformTransactionManager extends TransactionManager {
    
    
	TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
	void commit(TransactionStatus var1) throws TransactionException;
	void rollback(TransactionStatus var1) throws TransactionException;
}

Diferentes marcos de capa de persistencia pueden operar de diferentes maneras, por lo que diferentes marcos de capa de persistencia pueden tener diferentes implementaciones de administradores de transacciones de plataforma.
Por ejemplo: cuando se utiliza MyBatis como marco de capa de persistencia, la implementación del administrador de transacciones de la plataforma utilizada es DataSourceTransactionManager.
Cuando se utiliza Hibernate como marco de capa de persistencia, el administrador de transacciones de plataforma utilizado es HibernateTransactionManager.

En segundo lugar, la configuración de la información de definición de transacciones, cada transacción tiene muchas características, como: nivel de aislamiento, estado de solo lectura, tiempo de espera, etc., esta información se puede especificar a través de la conexión durante el desarrollo, y aquí se configura a través de archivos de configuración.

<tx:attributes>
	<tx:method name="方法名称"
			isolation="隔离级别"
			propagation="传播行为"
			read-only="只读状态"
			timeout="超时时间"/>
</tx:attributes>

Entre ellos, el nombre del atributo name especifica qué método realizará la configuración de atributos de qué transacciones.¿Qué se debe distinguir aquí es la diferencia entre el método especificado por la expresión pointcut y el método especificado aquí? La expresión de corte de punto es para filtrar qué métodos pueden realizar la mejora de la transacción; el nombre de la información del atributo de transacción es para especificar qué método configurar qué atributos de transacción.

inserte la descripción de la imagen aquí

Al configurar el nombre del método, también puede usar * para coincidencias parciales, por ejemplo:

<tx:advice id="myAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<!--精确匹配transferMoney方法-->
		<tx:method name="transferMoney"/>
		<!--模糊匹配以Service结尾的方法-->
		<tx:method name="*Service"/>
		<!--模糊匹配以insert开头的方法-->
		<tx:method name="insert*"/>
		<!--模糊匹配以update开头的方法-->
		<tx:method name="update*"/>
		<!--模糊匹配任意方法,一般放到最后作为保底匹配-->
		<tx:method name="*"/>
	</tx:attributes>
</tx:advice>

atributo de aislamiento: Especifica el nivel de aislamiento de la transacción.Hay tres problemas principales en la concurrencia de transacciones: lecturas sucias, lecturas no repetibles y lecturas fantasma/virtuales. Puede garantizar la aparición de problemas de simultaneidad configurando el nivel de aislamiento de la transacción; los más utilizados son READ_COMMITTED y REPEATABLE_READ.

inserte la descripción de la imagen aquí

atributo de solo lectura: establezca el estado actual de solo lectura. Si es una consulta, configúrelo en verdadero, lo que puede mejorar el rendimiento de la consulta. Si es una operación de actualización (adición, eliminación, modificación), configúrelo en falso.

<!-- 一般查询相关的业务操作都会设置为只读模式 -->
<tx:method name="select*" read-only="true"/>
<tx:method name="find*" read-only="true"/>

Atributo de tiempo de espera: establezca el tiempo de espera para la ejecución de la transacción, en segundos. Si se excede el límite de tiempo pero la transacción no se ha completado, la transacción se revertirá automáticamente y no continuará ejecutándose. El valor predeterminado es -1, es decir, no hay límite de tiempo de espera.

<!-- 设置查询操作的超时时间是3秒 -->
<tx:method name="select*" read-only="true" timeout="3"/>

Atributo de propagación: establece el comportamiento de propagación de la transacción, principalmente para resolver el problema del método de propagación de la transacción cuando el método A llama al método B. Por ejemplo: use una transacción unilateral, o tanto A como B usen su propia transacción, etc. El comportamiento de propagación de una transacción tiene los siguientes siete valores de propiedad que se pueden configurar:

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Analicemos el principio del control de transacciones declarativo en modo xml: el
procesador de espacio de nombres utilizado por la etiqueta <tx:advice> es TxNamespaceHandler, y el analizador registrado internamente es
TxAdviceBeanDefinitionParser

this.registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());

El BeanDefinition a registrar se especifica en TxAdviceBeanDefinitionParser

protected Class<?> getBeanClass(Element element) {
    
    
	return TransactionInterceptor.class;
}

El método parse de la clase principal secundaria AbstractBeanDefinitionParser de TxAdviceBeanDefinitionParser registra el TransactionInterceptor con el nombre configurado en el contenedor Spring.

parserContext.registerComponent(componentDefinition);

Se ejecutará el método de invocación en TransactionInterceptor, rastreará el método de invocación y, finalmente, verá la apertura y el envío de la transacción
⚫ La transacción se abrió en la línea 132 de AbstractPlatformTransactionManager;
⚫ La transacción se confirma en la línea 242 de TransactionAspectSupport.

4. Control de transacciones declarativo basado en anotaciones

Las anotaciones son una alternativa a xml

@Service("accountService")
public class AccoutServiceImpl implements AccountService {
    
    
	@Autowired
	private AccountMapper accountMapper;
	
	// <tx:method name="*" isolation="REPEATABLE_READ" propagation="REQUIRED“/>
	@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly = false,timeout = 5)
	public void transferMoney(String decrAccountName, String incrAccountName, int money) {
    
    
		accountMapper.decrMoney(decrAccountName,money); //转出钱
		int i = 1/0; //模拟某些逻辑产生的异常
		accountMapper.incrMoney(incrAccountName,money); //转入钱
	}
}

De manera similar, el administrador de transacciones de la plataforma aún debe configurarse para la anotación de transacciones utilizada y el interruptor de anotación de transacciones debe estar activado.

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

<!--配置事务的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>

Si usa anotaciones completas, use la siguiente clase de configuración en lugar del archivo de configuración:

@Configuration
@ComponentScan("com.itheima.service")
@PropertySource("classpath:jdbc.properties")
@MapperScan("com.itheima.mapper")
@EnableTransactionManagement
public class ApplicationContextConfig {
    
    
@Bean
public PlatformTransactionManager tansactionManager(DataSource dataSource){
    
    
	DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
	transactionManager.setDataSource(dataSource);
	return transactionManager;
}
	// ... 省略其他配置 ...
}

Supongo que te gusta

Origin blog.csdn.net/qq_36602071/article/details/129953523
Recomendado
Clasificación