spring boot aop

一、简介

AOP(Aspect Orient Programming),即面向切面编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理。

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

1.通知(有的地方叫增强)(Advice)
需要完成的工作叫做通知,就是你写的业务逻辑中需要比如事务、日志等

2.连接点(Join point)
就是spring中允许使用通知的地方

3.切点(Poincut)
筛选出的连接点,一个类中的所有方法都是连接点,但又不全需要,会筛选出某些作为连接点做为切点。

4.切面(Aspect)
通知和切点的结合,通知和切点共同定义了切面的全部内容

5.目标(target)
需要加入额外代码的对象

6.织入(Weaving)
把切面加入程序代码的过程。切面在指定的连接点被织入到目标对象中,在目标对象的生命周期里有多个点可以进行织入

编译期:切面在目标类编译时被织入,这种方式需要特殊的编译器

类加载期:切面在目标类加载到JVM时被织入,这种方式需要特殊的类加载器,它可以在目标类被引入应用之前增强该目标类的字节码

运行期:切面在应用运行的某个时刻被织入,一般情况下,在织入切面时,AOP容器会为目标对象动态创建一个代理对象,Spring AOP就是以这种方式织入切面的

二、流程

新建spring boot 项目

1.pom.xml 引入如下依赖:


	org.springframework.boot
	spring-boot-starter



	org.springframework.boot
	spring-boot-starter-aop

2.AopService.java

package com.vincent;

import org.springframework.stereotype.Service;

@Service
public class AopService {
	public void test() {
		System.out.println("AopService test----------");
	}
}

3.AopAspect.java

package com.vincent;

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.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AopAspect {
	@Pointcut(value = "execution(* com.vincent.*.*(..))")
	public void pointcut() {
		
	}
	
	@Before(value = "pointcut()")
	public void before(JoinPoint jp) {
		System.out.println("before--------------");
	}
	
	@AfterReturning(value = "pointcut()")
	public void afterReturn(JoinPoint jp) {
		System.out.println("afterReturn--------------");
	}
	
	@AfterThrowing(value = "pointcut()",throwing = "ex")
	public void afterThrowing(JoinPoint jp,Throwable ex) {
		System.out.println("afterThrowing--------------" + ex);
	}
	
	@After(value = "pointcut()")
	public void after(JoinPoint jp) {
		System.out.println("after--------------");
	}
	
	@Around(value = "pointcut()")
	public Object around(ProceedingJoinPoint jp) throws Throwable {
		System.out.println("around--------------");
		
		Object rst = null;
		
		rst = jp.proceed();
		
		return rst;
	}
	
}

4.Ch4Application.java

package com.vincent;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Ch4Application {

	public static void main(String[] args) {
		ApplicationContext ctx = SpringApplication.run(Ch4Application.class, args);
		ctx.getBean(AopService.class).test();
	}

}

三、测试

1.运行Ch4Application.java

spring boot aop_第1张图片

2.AopService.java test 方法抛出异常

public void test() {
	int x = 1/ 0;
	System.out.println("AopService test----------");
}

四、总结

1.@Aspect 注解表明这是一个切面类

2.@Pointcut 注解表明是一个切点定义

3.@Before 表明该方法是一个前置通知,该方法在目标方法执行之前执行,通过JoinPoint 参数可以获取目标方法的方法名、修饰符等信息

4.@After 注解使一个后置通知,该方法在目标方法执行之后执行

5.@AfterReturning 注解表示返回通知,该方法可以获取目标方法的返回值,@AfterReturning 注解的returning 参数是指返回值的变量名,对应方法的参数

6.@AfterThrowing 注解表示异常通知,当目标方法发送异常时该方法会被调用,异常类型为Exception 表示所有异常都会被该方法处理

7.@Around 注解表示环绕通知,可实现前置通知、后置通知、异常通知、返回通知,通过调用方法参数ProceedingJoinPoing 对象的proceed 方法是目标方法继续执行

8.@Pointcut也可以使用注解定义切点,在需要被代理的方法上添加注解即可

注解定义:

package com.vincent.aspect;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

}

切面定义:

package com.vincent.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LogAspect {
    @Pointcut("@annotation(com.vincent.aspect.PrintLog)")
    public void logPointCut(){}

    @Around("logPointCut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable{
        Object target = joinPoint.getTarget();
        Object args = joinPoint.getArgs();
        Object rst = joinPoint.proceed();
        return rst;
    }
}

注解方式将带来更大的灵活性、细粒度,在需要被代理的方法上添加注解即可。springboot 中很多都使用注解实现AOP如:@Cacheable等

你可能感兴趣的:(spring,boot,spring,boot,aop)