Ruta de aprendizaje JavaWeb (9) - gestión de transacciones y AOP

1. Gestión de transacciones

  • Concepto: Una transacción es una colección de operaciones que son atómicas y tienen éxito o fallan.
  • Función: cuando ocurre una excepción, puede controlar de manera efectiva que los datos no se pierdan.
  • Cómo usar - Notas

(1) Anotación de transacción @Transactional

  • Ubicación: en el método de la capa empresarial (Servicio), en la clase, en la interfaz
  • Función: Entregar el método actual a Spring para su administración. Antes de que se ejecute el método, inicie la transacción; después de la ejecución exitosa, envíe la transacción; si ocurre una excepción, revierta la transacción.
//接口上
@Transactional
public interface EmpService{
    
    
	void delete(Integer id);
}

//类上
@Transactional
class EmpController implements EmpService{
    
    
	//方法上
	@Transactional
	@Override
	public void delete(Integer id){
    
    
		//处理代码
	}
}

(2) Parámetros de transacciones comunes ,
1. rollbackPara el atributo de reversión de transacciones

(1) Motivo de la configuración: @Transactional solo se puede revertir cuando se produce una excepción de tiempo de ejecución de forma predeterminada.

(2) Establezca la propiedad de reversión de transacciones: @Transactional( rollbackFor = Exception.class )

2. Comportamiento de propagación de transacciones de propagación

(1) Concepto: cuando otro método físico llama a un método de transacción, ¿cómo realiza esta transacción el control de transacción?
(2) Comportamiento de propagación común

comportamiento comunicativo ilustrar
REQUERIDO (requerir; necesitar) De forma predeterminada, se requiere una transacción, si hay una transacción, únase a la transacción, si no hay transacción, cree una transacción
REQUIRES_NEW (requerir nuevo) Se requiere una nueva transacción, siempre se crea una transacción con o sin
SOPORTES Transacciones de soporte, si hay una, únase a la transacción, si no, ejecute en el estado de no transacción
NO SOPORTADO No admite transacciones, se ejecuta sin estado de transacción, si hay una transacción, suspende la transacción actual
OBLIGATORIO Debe haber una transacción, de lo contrario se lanzará una excepción
NUNCA No debe haber ninguna transacción, de lo contrario se lanzará una excepción.

2. POA

(1) Fundación AOP

  • Concepto: La Programación Orientada a Aspectos (programación orientada a aspectos, programación orientada a aspectos) es en realidad programación orientada a métodos .
  • Función: programa un método específico a través del mecanismo de proxy dinámico .
  • Escenarios de uso de AOP
    • registrar registro de operaciones
    • control de acceso
    • gestión de asuntos
  • Ventajas de AOP
    • Sin intrusión de código: no cambie el cuerpo de ejecución del método original
    • Reducir código duplicado: extraer código de operación común
    • Mejore la eficiencia del desarrollo: se pueden realizar operaciones unificadas
    • Fácil mantenimiento: Al cambiar códigos adicionales o códigos originales, no es necesario modificarlos secuencialmente.
  • usar AOP
    • agregar dependenciasorg.springframework.boot.spring-boot-starter-aop
    • Escribir programa AOP
@Component //Spring容器进行管理
@Aspect //声明AOP
public class TimeAspect{
    
    
	//@Around —— 环绕通知 
	//execution(返回值 作用的包名.类/接口.方法(参数)) —— 启动范围
	@Around("execution(* com.zengoo.service.*.*(..))")
	public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable{
    
    
		//1.记录时间
		long begin = System.currentTimeMillis();
		//2.运行原始方法
		//ProceedingJoinPoint 是原始方法切入点
		Object result = joinPoint.proceed();
		//3.记录时间
		long end = System.currentTimeMillis();
		
		return result;
	}
}

(2) El concepto central de AOP
1. Punto de conexión: JoinPoint, todos los métodos pertenecen al punto de conexión.
2. Aviso: el consejo se refiere al método común, es decir, el método de procesamiento de AOP.
3. Punto de entrada: PointCut, el método realmente controlado por AOP.
4. Aspecto: Aspecto, que describe la correspondencia entre notificaciones y puntos de entrada, y la recopilación de todos los aspectos se coloca en la clase de aspecto.
5. Objeto objetivo: objetivo, el método de control real de AOP.

@Component
@Aspect
public DemoAspect{
    
    
	//抽取切入点表达式
	@PointCut("execution(* com.zengoo.service.*.*(..))")
	public void pt(){
    
    }
	//切面
	@Around("pt()") //引用切入点
	//通知
	public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
    
    
		//前置代码...
		//目标对象
		Object result = proceedingJoinPoint.proceed();
		//后置代码...
		return result;
	}
}

(3) Detalles del parámetro AOP
1. Tipo de notificación

tipo de notificación ilustrar
@Alrededor Notificación envolvente, el método de notificación marcado por esta anotación se ejecuta antes y después del método de destino.
@Antes Notificación previa, el método de notificación marcado por esta anotación se ejecuta antes que el método de destino.
@Después Después de la notificación, el método de notificación anotado por esta anotación se ejecuta después del método de destino, independientemente de si se produce una excepción.
@Después de regresar Notificación tras devolución, el método de notificación marcado por esta anotación se ejecuta después del método de destino y la ejecución se cancelará si se produce una excepción.
@después de lanzar Notificación tras excepción, el método de notificación marcado con esta anotación se ejecuta tras excepción.

2. Orden de notificación

(1) Entre las diferentes clases de aspecto, la clasificación se realiza de forma predeterminada según el nombre de clase de la clase de aspecto (complejo)

  • Antes de la notificación: cuanto más alto sea el ranking, el primero en ejecutar. (en la pila)
  • After Notice: Ejecutar primero después de la prueba de clasificación. (estallido)

(2) Prioridad de control @Order (número)

  • Antes de la notificación: los números más pequeños se ejecutan primero.
  • Después del aviso: el número más grande se ejecutará primero.
@Order(1) //最先执行Before,最后执行After
public class MyAspect1{
    
    
	...
}

@Order(2//最后执行Before,最先执行After
class MyAspect2{
    
    
	...
}

3. Expresión del punto de entrada

(1) Concepto: Una expresión que describe el método de punto de entrada
(2) Función: Métodos coincidentes en el proyecto para agregar notificaciones
(3) Formas comunes:

  • execution([访问修饰符] 返回值 [包名.类名.]方法名(方法参数) [throws 异常]): coincide con la firma del método

    • comodín
      • * : Un único carácter arbitrario independiente, comodín cualquier valor de retorno, nombre de paquete, nombre de clase, nombre de método, parámetro o parte del nombre.
      • : Múltiples símbolos arbitrarios consecutivos, comodines de cualquier nivel de paquetes o cualquier tipo y cualquier número de parámetros
    • emparejamiento multimétodo
      • ||, &&, ! : utilizado para la coincidencia de múltiples métodos específicos
    • consejos de escritura
      • Los nombres de los métodos de todas las empresas deben nombrarse lo más estandarizados posible para facilitar la coincidencia rápida de las expresiones del punto de entrada. Por ejemplo, el método de clase de consulta comienza con consultar o buscar, y el método de clase de actualización comienza con actualizar o modificar.
      • El método pointcut de descripción generalmente se basa en la descripción de la interfaz para mejorar la escalabilidad .
      • Bajo la premisa de satisfacer al negocio, intenta acotar el ámbito de coincidencia del punto de entrada .
  • execution(@annotation(...)): coincidencia según la anotación

//自定义一个注解
@Retention(RetentionPolicy.RUNTIME) //生效时间
@Target(ElementType.METHOD) //作用位置
public @interface MyAnnotation{
    
    }


@Service
class xxxServiceImpl implements xxxService{
    
    
	//标记切入点
	@MyAnnotation
	@Override
	public xxx xxx(){
    
     return xxx; }
}

@Component
@Aspect
class MyAspect{
    
    
	//匹配所有加上了 @MyAnnotation 的方法
	@PointCut(@annotation("com.zengoo.annotation.MyAnnotation"))
	public void ptAnnotation(){
    
    }
	
	@Before("ptAnnotation()")
	public void xxx(){
    
    
		...
	}
}

4. Punto de conexión

Spring usa JoinPoint para abstraer el punto de conexión, lo que guarda información relevante cuando se ejecuta el método, como el nombre de la clase de destino, el nombre del método, los parámetros del método, etc.

  • Para consejos de @Around, useProceedingJoinPoint
  • Las otras cuatro notificaciones usan JoinPoint, que es ProceedingJoinPointel tipo principal de.
@Before
public void testxxx(JoinPoint joinPoint){
    
    };
Implementación ilustrar
joinPoint.getTarget().getClass().getName() obtener el nombre de la clase
joinPoint.getSignature().getName() obtener el nombre del método
unirPunto.getArgs() Obtener los parámetros pasados ​​en tiempo de ejecución
unirPunto.proceder() ejecutar el método de destino
El valor de retorno de joinPoint.proceed() obtener valor de retorno

(4) Caso AOP - registro de operaciones

(1) Información de registro de operaciones

  • Operador
  • tiempo de funcionamiento
  • El nombre completo de la clase del método de ejecución.
  • nombre del método de ejecución
  • Parámetros en tiempo de ejecución del método
  • valor devuelto
  • tiempo de ejecución del método

(2) darse cuenta

  • Preparación

Dependencia de AOP y dependencia de lombok

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
</dependency>

estructura de la base de datos

create table operate_log(
	id int usigned primary key auto_increment comment '操作ID',
	operate_user int unsigned comment '操作人ID',
	operate_time datetime comment '操作时间',
	class_name varchar(100) comment '执行方法的全类名',
	method_name varchar(100) comment '执行方法名',
	method_params varchar(1000) comment '方法运行时的参数',
	return_value varchar(2000) comment '返回值',
	cost_time bigint comment '方法执行时长,单位:ms'
) comment '操作日志表'

clase de entidad

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog{
    
    
	private Integer id;
	private Integer operateUser;
	private LocalDateTime operatetime;
	private String className;
	private String methodName;
	private String methodParams;
	private String returnValue;
	private Long costTime;
}
  • codificación

Anotación personalizada @Log

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
    
    

}

Defina la clase de aspecto para completar la lógica de registro del registro de operaciones

@Component
@Aspect
public class OperateAspect {
    
    

	@Autowired
	private HttpServletRequest request;

	@Autowired
	private OperateLogMapper operateLogMapper;

    @Pointcut("@annotation(com.zengoo.annotation.Log)")
    public void pc(){
    
    }

    @Around("pc()")
    public Object operateLog(ProceedingJoinPoint joinPoint) throws Throwable {
    
    

		//操作人的ID
		//获取令牌并解析
		String jwt = request.getHeader("token");
		Claims claims = JwtUtils.parseJWT(jwt);
		Integer operateUser = (Integer) claims.get("id");
		
		//操作时间
		LocalDateTime operateTime = LocalDateTime.now();
		
		//操作类名
		String className = joinPoint.getTarget().getClass.getName();

		//操作方法名
		String methodName = joinPoint.getSignature().getName();
	
		//传入的形参列表
		Object[] args = joinPoint.getArgs();
		String methodParams = Arrays.toString(args);
		
		Long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        Long end= System.currentTimeMillis();
        
		//返回值
		Stirng returnValue = JSONObject.toJSONString(result);

		//耗时
		Long costTime = end - start;
		
		//记录操作日志
		//该方法是插入记录的sql
		OperateLog operateLog = new OperateLog(	
				null,
				operateUser,
				operateTime,
				className,
				methodName,
				methodParams,
				returnValue,
				costTime
		);
		operateLogMapper.record(operateLog); 
		
        return result;
    }
}

Supongo que te gusta

Origin blog.csdn.net/Zain_horse/article/details/131461502
Recomendado
Clasificación