Understanding of Spring AOP and project application

Byte’s questions about Spring AOP gave me the idea of ​​having an in-depth understanding of Spring AOP. Now let’s sort out my understanding of Spring AOP.

class A{
    
    
	@Logxxx
	public void methodA(){
    
    
		methodB();
	}
	
	@Logxxx
	public void methodB(){
    
    
	}
}

Question:
There are two methods, methodA and methodB, in class A. The methods have custom annotations @Logxxx. The function of @Logxxx is to output a log after the method is executed. If method methodA is executed, how many times will the log information be output?
Conclusion:
Only method methodA outputs a log after execution.
Reason:
When calling method methodA, because the @Logxxx log is added, spring aop will generate a proxy object, but the object used when executing methodB method is not a proxy object, so it will not be enhanced.

My understanding:
Understanding of aop:
1. What is aop: Aspect-oriented programming, a technology that enhances program functions through pre-compilation or run-time dynamic compilation.
2. AOP can intercept specified methods and enhance them without adding requirement code to the code, thus separating business code from non-business code.
3. AOP adopts a horizontal extraction mechanism (dynamic proxy) to replace the repetitive code of the traditional vertical inheritance mechanism. Its application is mainly reflected in transaction processing, log management, permission control, exception handling, etc.
4. In layman’s terms, it means performing certain processing before and after code execution, such as logging, permission verification and other
AOP terms:

	对象术语:描述aop中各个对象的部分
			连接点(Join Point):所有符合条件的切点的集合,可能有一个或者多个我们成为连接点。
			切入点/切点(Pointcut):切点是指通知(Advice)所要织入(Weaving)的具体位置,满足我们条件的目标方法。
			比如使用自定义注解,切点就是这个注解所标志的地方。比如我们指定规则,以find开头的才执行我们自定义通	知,那么这些满足条件的以find开头的方法就是切点。
			切面 (Aspect):切点和通知的组合叫法。连接点是我们没有定义那个find开头规则时,满足条件的全部的方法。
			通知/增强(Advice):我们编写的希望在aop时执行的方法,通常希望在目标方法前后执行。
				五种通知:
					前置通知(Before):在目标方法被调用前执行的行为。
					后置通知(After):在目标方法执行完成后执行的行为,不能获取到方法的输出。
					后置返回通知(After-returning):在目标方法成功执行后执行的行为,可以获取到方法的输出。
					后置异常通知(After-throwing):在目标方法抛出异常后执行的行为。
					环绕通知(Around):包裹了目标方法,可以在其执行前后执行自定义的行为。
		行为术语:aop实现过程中涉及的具体行为
			引入(Introduction):向现有类中添加新的方法和属性,我们可以把切面的属性引入到目标类。
			织入(Weaving):织入指的是将切面应用到目标对象,在这个过程中会生成新的代理对象。
				织入三种时期
					 编译期:在目标类被编译时进行织入,需要依赖于特殊的编译器。AspectJ 的织入编译器就采用的这种方式。
					 类加载期:在目标类被加载到 JVM 时进行织入,需要依赖于特殊的类加载器。这种方式会在目标类被引入应用前增强目标类的字节码。
					 运行期:在应用运行的某一具体时刻进行织入。在这种情况下,AOP 容器会为目标对象动态地创建一个代理对象,Spring AOP 就采用的这种方式。
		具体例子理解:
				被增强的方法:王老师的语文课
				目标方法所在类:王老师
				通知(前置通知):做某事前擦黑板,重点是擦黑板这一行为
				连接点:老师上课前的时间,并不确定是哪些老师上哪门课前
				切点:王老师上语文课前这一时间点
				切面:在王老师上语文课前擦黑板

The implementation mechanism of Spring AOP
spring implements AOP through dynamic proxy and dynamic bytecode.
Dynamic proxy: JDK dynamic proxy and CGLIB dynamic proxy.

	1. JDK动态代理:Spring AOP的首选方法,当目标对象实现一个接口时可以使用JDK动态代理。
	2. CGLIB代理:目标对象如果没有实现接口,可以使用CGLIB代理,原理是继承实现的所以不能代理final,static修饰的目标类,并且方法不能用private修饰。

My application in the project-custom log annotation

//自定义注解
@Retention(RetentionPolicy.RUNTIME) //该注解用来修饰注解的生命周期
@Target(value = {
    
    ElementType.METHOD})// 表示该注解的作用范围
@Documented //有该注解的注解生成javadoc的时候是否会被记录
public @interface Log{
    
    
    int level() default 2;
}
//定义切面 
@Component
@Aspect
@RequiredArgsConstructor
@Slf4j
public class LogAspect {
    
    
 	//切点
    @Pointcut("@annotation(com.xx.xx.xx.Log)")
    public void printLog(){
    
    

    }
 
    /**
     * 输出日志
     * @param joinPoint
     */
    @After(value = "printLog()")
    public void doAfterPrintLog(JoinPoint joinPoint){
    
    
        //获取参数
        Object[] args = joinPoint.getArgs();
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        // 反射获取目标类
        Class<?> targetClass = joinPoint.getTarget().getClass();
        // 拿到方法对应的参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        // 根据类、方法、参数类型(重载)获取到方法的具体信息
        Method objMethod = null;
        try {
    
    
            objMethod = targetClass.getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
    
    
            e.printStackTrace();
        }
        // 拿到方法定义的注解信息
        PreAuthCheck annotation = objMethod.getDeclaredAnnotation(Log.class);
        System.out.println("日志级别:"annotation.level());
    }

}

Guess you like

Origin blog.csdn.net/qq_36488864/article/details/130243331