JavaWeb learning route (9) - transaction management and AOP

1. Transaction management

  • Concept: A transaction is a collection of operations that are atomic and either succeed or fail.
  • Function: When an exception occurs, it can effectively control the data from being lost.
  • How to use - Notes

(1) Transaction annotation @Tranactional

  • Location: on the business layer (Service) method, on the class, on the interface
  • Function: Hand over the current method to Spring for management. Before the method is executed, start the transaction; after successful execution, submit the transaction; if an exception occurs, roll back the transaction.
//接口上
@Transactional
public interface EmpService{
    
    
	void delete(Integer id);
}

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

(2) Common transaction parameters ,
1. rollbackFor transaction rollback attribute

(1) Reason for setting: @Transactional can only be rolled back when a Runtime exception occurs by default.

(2) Set the transaction rollback property: @Transactional( rollbackFor = Exception.class )

2. Propagation transaction propagation behavior

(1) Concept: When a transaction method is called by another physical method, how does this transaction perform transaction control
(2) Common propagation behavior

communication behavior illustrate
REQUIRED (require; need) By default, a transaction is required, if there is a transaction, join the transaction, if there is no transaction, create a transaction
REQUIRES_NEW (require new) A new transaction is required, a transaction is always created with or without
SUPPORTS Support transactions, if there is one, join the transaction, if not, run in the state of no transaction
NOT_SUPPORTED Does not support transactions, runs in no transaction state, if there is a transaction, suspends the current transaction
MANDATORY There must be a transaction, otherwise an exception will be thrown
NEVER There must be no transaction, otherwise an exception will be thrown

2. AOP

(1) AOP foundation

  • Concept: Aspect Oriented Programming (aspect-oriented programming, aspect-oriented programming) is actually method-oriented programming .
  • Function: Program a specific method through the dynamic proxy mechanism.
  • AOP usage scenarios
    • record operation log
    • access control
    • affairs management
  • Advantages of AOP
    • No code intrusion: do not change the original method execution body
    • Reduce Duplicate Code: Extract Common Operation Code
    • Improve development efficiency: Unified operations can be performed
    • Easy maintenance: When changing additional codes or original codes, there is no need to modify them sequentially.
  • use AOP
    • add dependenciesorg.springframework.boot.spring-boot-starter-aop
    • Write AOP program
@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) The core concept of AOP
1. Connection point: JoinPoint, all methods belong to the connection point.
2. Notice: Advice refers to the common method, that is, the processing method of AOP.
3. Entry point: PointCut, the method actually controlled by AOP.
4. Aspect: Aspect, which describes the correspondence between notifications and entry points, and the collection of all aspects is placed in the aspect class.
5. Target object: Target, the actual control method of 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) AOP parameter details
1. Notification type

notification type illustrate
@Around Surround notification, the notification method marked by this annotation is executed before and after the target method.
@Before Pre-notification, the notification method marked by this annotation is executed before the target method.
@After Post-notification, the notification method annotated by this annotation is executed after the target method, regardless of whether an exception occurs.
@AfterReturning Notification after return, the notification method marked by this annotation is executed after the target method, and the execution will be canceled if an exception occurs.
@AfterThrowing Notification after exception, the notification method marked with this annotation is executed after exception.

2. Notification order

(1) Among different aspect classes, sorting is done by default according to the class name of the aspect class (complex)

  • Before notification: the higher the ranking, the first to execute. (into the stack)
  • After Notice: Execute first after the ranking test. (pop)

(2) @Order (number) control priority

  • Before notification: Smaller numbers are executed first.
  • After notice: the largest number will be executed first.
@Order(1) //最先执行Before,最后执行After
public class MyAspect1{
    
    
	...
}

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

3. Entry point expression

(1) Concept: An expression describing the entry point method
(2) Function: Matching methods in the project to add notifications
(3) Common forms:

  • execution([访问修饰符] 返回值 [包名.类名.]方法名(方法参数) [throws 异常]): match against the method signature

    • wildcard
      • * : A single independent arbitrary character, wildcard any return value, package name, class name, method name, parameter or part of the name.
      • : Multiple consecutive arbitrary symbols, wildcarding any level of packages or any type and any number of parameters
    • multi-method matching
      • ||, &&, ! : used for matching of multiple specific methods
    • writing advice
      • The method names of all businesses should be named as standardized as possible to facilitate quick matching of entry point expressions. For example, the query class method starts with query or find, and the update class method starts with update or modify.
      • The description pointcut method is usually based on the interface description to enhance scalability .
      • Under the premise of satisfying the business, try to narrow the matching scope of the entry point .
  • execution(@annotation(...)): match according to annotation

//自定义一个注解
@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. Connection point

Spring uses JoinPoint to abstract the connection point, which saves relevant information when the method is executed, such as the target class name, method name, method parameters, etc.

  • For @Around advice, useProceedingJoinPoint
  • The other four notifications use JoinPoint, which is ProceedingJoinPointthe parent type of.
@Before
public void testxxx(JoinPoint joinPoint){
    
    };
Implementation illustrate
joinPoint.getTarget().getClass().getName() get class name
joinPoint.getSignature().getName() get method name
joinPoint.getArgs() Get the parameters passed in at runtime
joinPoint.proceed() run target method
The return value of joinPoint.proceed() get return value

(4) AOP case - operation log

(1) Operation log information

  • Operator
  • operating time
  • The full class name of the executing method
  • Execution method name
  • Parameters at method runtime
  • return value
  • method execution time

(2) Realize

  • Preparation

AOP dependency and lombok dependency

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

database structure

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 '操作日志表'

Entity class

@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;
}
  • coding

Custom annotation @Log

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

}

Define the aspect class to complete the logic of recording the operation log

@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;
    }
}

Guess you like

Origin blog.csdn.net/Zain_horse/article/details/131461502