Configure AOP through annotations

AOP introduction

Reference blog post

Spring AOP-aspect-oriented programming in Spring

1. What is AOP thinking?

AOP (Aspect Orient Programming), literally translated is aspect-oriented programming. AOP is a programming idea and a supplement to object-oriented programming (OOP). Object-oriented programming abstracts programs into various levels of objects, while aspect-oriented programming abstracts programs into various aspects.

Picked up a picture from the book "Spring Actual Combat (4th Edition)":
Insert picture description here

2. What is AOP generally used for

  1. Transaction processing: Before executing the method, open the transaction, close the transaction after the execution is completed, and roll back the transaction when an exception occurs
  2. Judgment of authority: before executing the method, judge whether it has authority
  3. Log: log processing before execution

For example, you want to record user access logs for your website:
some URLs do not need to be recorded, and some need to be recorded.
If you still use OOP, object-oriented,
then you can only use the Controller corresponding to those URLs In the code, one by one is written on the log records.
And what if you use AOP?
There is no need to add code to the control class, but directly add a log class to record logs non-invasively through aspects.

3. Advantages of AOP

  1. Reduce repetitive code
  2. Improve development efficiency
  3. Easy maintenance

4. AOP related terms

the term significance
Joinpoint (connection point) The so-called connection points are those points that are intercepted. In spring, these points refer to methods, because spring only supports connection points of method types.
Pointcut (entry point) The so-called entry point refers to the definition of which Joinpoint we want to intercept.
Advice The so-called notification refers to the notification after intercepting Joinpoint. Notification types: pre-notification, post-notification, exception notification, final notification, surround notification.
Proxy After a class is woven and enhanced by AOP, a result proxy class is generated.
Aspect It is a combination of entry point and notification (introduction).
Introduction(引介) Introduction is a special kind of notification. On the premise of not modifying the class code, Introduction can dynamically add some methods or fields to the class at runtime.
Target The target object of the agent.

Configure AOP by way of annotation

1. Pointcut grammar

Insert picture description here
We use the execution indicator to select the play method of Instrument. The method expression starts with an * to indicate that we do not care about the return value type of the method. Then we specified the fully qualified class name and method name. For the method parameter list, we use... to identify the cut point to select any play method, no matter what the input parameters of the method are.
We can use more than one match between the link symbol &&, ||, to mean "and", "or" relationship "not" of. But when using XML file configuration, these symbols have special meaning, so we use " and"," or", " not”to indicate.

For example:
limit the pointcut to only match the package com.sharpcj.aopdemo.test1, you can use

execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)) && within(com.sharpcj.aopdemo.test1.*)

Select bean in the cut point, you can use

execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..)) && bean(girl)

2. Five notification types

Comment (name) effect
@Before The notification method will be executed before the target method is called
@After The notification method will be called after the target method returns or abnormal
@AfterReturning The notification method will be called after the target method returns, if an exception occurs, it will not be called
@AfterThrowing The notification method will be called after the target method throws an exception
@Around (surround notification) The notification method encapsulates the target

3. Simple example

User class

package test_aop.pojo;

import org.springframework.stereotype.Component;

@Component
public class User {
    
    

	public String point(boolean s) {
    
    

		System.err.println("User.point() arg s is==" + s);

		return "message";
	}

}

AdviceConfig class

package test_aop.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

// 一定要是用aspect注解
// true代表使用cglib代理方式(使用注解)  false代表使用jdk动态代理模式
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Component
@Aspect
public class UserAdvice {
    
    

	// 方法路径
	final static String FUNTION_NAME = "execution(* test_aop.pojo.User.point(..))";

	// 在point调用之前执行
	// point参数代表当前的目标方法,我们可以通过这个参数获取目标方法的 参数,返回值等相关信息
	@Before(value = FUNTION_NAME)
	public void before(JoinPoint point) {
    
    
		System.out.println("UserAdvice.before()");
	}

	// 在point调用之后执行
	// point参数代表当前的目标方法,我们可以通过这个参数获取目标方法的 参数,返回值等相关信息
	@After(value = FUNTION_NAME)
	public void after(JoinPoint point) {
    
    
		System.out.println("UserAdvice.after()");
	}

	// 该通知方法会目标方法返回后调用,如果出现异常则不会调用
	// returning参数指定用什么参数名接受返回的值
	@AfterReturning(pointcut = FUNTION_NAME, returning = "re")
	public void afterReturning(Object re) {
    
    
		System.out.println("UserAdvice.afterReturning() re==" + re);
	}

	// 该通知方法会在目标方法抛出异常后调用
	// throwing参数指定用什么名称的参数接受异常
	@AfterThrowing(pointcut = FUNTION_NAME, throwing = "e")
	public void afterThrowing(Exception e) {
    
    
		System.err.println(e);
	}

	// 该通知法会将目标封装起来,必须执行proceed方法,相当与放行的操作
	@Around(value = FUNTION_NAME)
	public void arround(ProceedingJoinPoint p) throws Throwable {
    
    

		System.out.println("UserAdvice.arround() before");
		p.proceed();
		System.out.println("UserAdvice.arround() after");

	}
}

main class

package test_aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import test_aop.pojo.User;

@SpringBootApplication
// 扫描注解
@ComponentScan(basePackages = {
    
     "test_aop.pojo", "test_aop.advice" })
public class App {
    
    

	public static void main(String[] args) {
    
    
		ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
		User user = context.getBean(User.class);
		user.point(true);
	}

}

result
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_42418169/article/details/112847020