springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解

声明:代码是JavaEE开发的颠覆者 Spring Boot实战代码中的,我只是拿去学习。

 

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第1张图片

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
    String name();
}




@Configuration
@ComponentScan("com.wisely.highlight_spring4.ch1.aop")
@EnableAspectJAutoProxy //1 开启对AOP的支持
public class AopConfig {

}



@Service
public class DemoAnnotationService {
	@Action(name="注解式拦截的add操作")
    public void add(){} 
   
}



@Service
public class DemoMethodService {
	public void add(){}
}




@Aspect //1 声明切面
@Component //2
public class LogAspect {
	
	@Pointcut("@annotation(com.wisely.highlight_spring4.ch1.aop.Action)") //3
	public void annotationPointCut(){};
	
	  @After("annotationPointCut()") //4
	    public void after(JoinPoint joinPoint) {
	        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
	        Method method = signature.getMethod();
	        Action action = method.getAnnotation(Action.class); 
	        System.out.println("注解式拦截 " + action.name()); //5
	    }
	  
	   @Before("execution(* com.wisely.highlight_spring4.ch1.aop.DemoMethodService.*(..))") //6
	    public void before(JoinPoint joinPoint){
	        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
	        Method method = signature.getMethod();
	        System.out.println("方法规则式拦截,"+method.getName());

	    }
}



public class Main {
	public static void main(String[] args) {
		 AnnotationConfigApplicationContext context =
	                new AnnotationConfigApplicationContext(AopConfig.class); //1
		 
		 DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
		 
		 DemoMethodService demoMethodService = context.getBean(DemoMethodService.class);
		 
		 demoAnnotationService.add();
		 
		 demoMethodService.add();
		 
		 context.close();
	}
}

测试结果:

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第2张图片

 

 

@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解

 

连接点(Joinpoint) :

程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。——可以理解为被aop拦截的类或者方法就是连接点。

通知(Advice) :

通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。——可以理解为被注解有@Before等advice注解的安全校验的方法,拦截了过来的请求要做什么逻辑的校验。

切入点(Pointcut) :

通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称。——可以理解为切面切向哪里?是个类或者某层的包路径。


目标对象(Target Object) :

即被通知的对象。


AOP代理(AOP Proxy)

在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,TargetObject实现了接口时,则采用JDK动态代理;反之,采用CGLIB代理。
织入(Weaving)把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才能做到,例如AspectJ的织入编译器;
(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码;
(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理是使用了JDK的动态代理。

 

通知(Advice)类型的说明

  • @Before 前置通知(Before advice) :在某连接点(JoinPoint)——核心代码(类或者方法)之前执行的通知,但这个通知不能阻止连接点前的执行。为啥不能阻止线程进入核心代码呢?因为@Before注解的方法入参不能传ProceedingJoinPoint,而只能传入JoinPoint。要知道从aop走到核心代码就是通过调用ProceedingJionPoint的proceed()方法。而JoinPoint没有这个方法。
    • 这里牵扯区别这两个类:Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到JoinPoint,这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。建议看一下 JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。这样你就能明白 proceed方法的重要性。
  • @After 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • @AfterReturning 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。
  • @Around 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。这时aop的最重要的,最常用的注解。用这个注解的方法入参传的是ProceedingJionPoint pjp,可以决定当前线程能否进入核心方法中——通过调用pjp.proceed();
  • @AfterThrowing 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。

 

advice(通知)注解的执行先后顺序

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第3张图片

测试

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第4张图片

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第5张图片

测试正常

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第6张图片

 

 

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第7张图片

测试异常

 

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第8张图片

springBoot AOP测试+@Before,@Around,@After,@AfterReturn,@AfterThrowing的理解_第9张图片

你可能感兴趣的:(SpringBoot)