AOP简介

AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面,是Spring的核心思想之一。

AOP实现

Spring中的aop是通过动态代理实现的,那么他具体是如何实现的呢?Spring通过一个切面类,在他的类上加入@Aspect 注解,定义一个Pointcut方法,最后定义一系列的增强方法。这样就完成一个对象的切面操作。

使用注解实现Spring AOP

Spring AOP通知类型

  • @Before:前置通知,在目标方法执行之前运行的通知,但不能阻止执行流继续到连接点(除非抛出异常)
  • @AfterReturning:返回后通知,在目标方法正常返回之后运行的通知(即一个方法正常返回而且没有抛出异常)
  • @AfterThrowing:抛出异常后通知,在目标方法通过抛出异常退出,则运行AfterThrowing通知
  • @After:后置通知,在目标方法运行结束之后,不管目标是否正常退出或者异常返回都将运行的通知
  • @Around:环绕通知,环绕目标方法的通知,环绕通知可以在方法调用之前和之后执行自定义行为

AOP注解

  • @Aspect:作用是把当前类标识为一个切面供容器读取
  • @Pointcut:切入点,可以定义表达式或者方法签名
  • @EnableAspectJAutoProxy:用于开启Spring Aop注解的功能

service接口类

public interface TestService {
    void test();
}

service实现类将实现类注入到Spring容器中

@Service
public class TestServiceImpl implements TestService {
    @Override
    public void test() {
        System.out.println("TestService的Test()方法执行");
    }
}

创建一个controller其中把service类注入到controller中,同时把controller注册到ioc容器中

@Component("TestController")
public class TestController {

    @Autowired
    private TestService testService;

    public void Test(){
        testService.test();
    }
}

定义一个切面类并且注册到ioc容器中

切入点表达式看你项目实现类的package

//切面类
@Aspect
@Component
public class TestAspect {

    //定义切入点
    @Pointcut("execution(* com.example.springaop.service.impl..*.*(..))")
    private void pointcut(){

    }

    //环绕通知
    @Around("pointcut()")
    //ProceedingJoinPoint 连接点对象
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Exception {
        //获取签名
        Signature signature = proceedingJoinPoint.getSignature();
        //获取目标方法名称
        String methodName = signature.getName();
        System.out.println("开始执行环绕通知,方法名称"+ methodName);
        try{
            long startTime = System.currentTimeMillis();
            //执行实现类test方法
            Object proceed = proceedingJoinPoint.proceed();
            long endTime = System.currentTimeMillis();
            System.out.println(methodName + "方法耗时:" + (endTime - startTime) + "毫秒");
            return proceed;
        }catch (Throwable throwable){
            throwable.printStackTrace();
            throw new Exception("方法异常");
        }
    }


    //前置通知
    @Before("pointcut()")
    public void before(JoinPoint joinpoint){
        String methodName = joinpoint.getSignature().getName();
        System.out.println("开始执行前置通知,方法名称"+ methodName);
    }

    //后置通知
    @After("pointcut()")
    public void after(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("开始执行后置通知,方法名称"+ methodName);
    }

    //返回通知
    @AfterReturning("pointcut()")
    public void afterReturning(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("开始执行后置返回通知,方法名称"+ methodName);
    }

    //异常通知
    @AfterThrowing("pointcut()")
    public void afterThrowing(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("开始执行抛出异常返回通知,方法名称"+ methodName);
    }

}

定义一个aop config配置类

@Configuration
//开启Aop注解
@EnableAspectJAutoProxy
@ComponentScan("com.example.springaop")
public class AopConfig {
}

测试运行

@Test
void contextLoads() {
    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
    TestController testController = (TestController) annotationConfigApplicationContext.getBean("TestController");
    testController.Test();
}

spring aop横向机制 spring aop具体实现_java


模拟异常情况

spring aop横向机制 spring aop具体实现_java_02