SpringAOP的基本使用------基础版

代码地址
demo
觉得博主还可以给个Star

AOP
aop:面向切面编程,针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。一般使用在方法上,对方法进行调用前后的处理。
应用场景:日志、事务、安全控制、计算方法耗时
核心通知:前置通知,后置通知,环绕通知,运行通知,异常通知
原理:动态代理模式
目前的动态代理有:

  1. JDK动态代理,实现InvocationHandler,底层使用反射技术,是基于接口实现代理
  2. cglib动态代理,基于asm 基于类实现代理 继承模式
    下面我们来了解一下怎么使用(案例中的应用场景为事务)
    我们先来了解一下简单问题
    1.在我们使用切面中需要要到@Aspect,但是这个注解我们会发现它并不在aop的jar包中,那么我们引入的时候需要加入另一个pom配置
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.6</version>
  <scope>compile</scope>
</dependency>

2.也就是最重要的开启aop,用到的注解为@EnableAspectJAutoProxy,我们点击进去发现,它只是@Import({AspectJAutoProxyRegistrar.class})这一个类,而这个类就是我们aop的核心,之后我会在源码的时候分析出来
3.前面提到了五个核心通知,我们一步一步示范
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
    </dependencies>
</project>

LogAop.java

package com.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAop {
    
    

    //定义切入点 开始方法拦截的入口
    @Pointcut("execution(* com.service..*.*(..))")
    public void logAop(){
    
    

    }

    @Before("logAop()")
    // 前置通知
    public void doBefore(){
    
    
        System.out.println("Before");
    }

    @After("logAop()")
    // 后置通知
    public void doAfter(){
    
    
        System.out.println("After");
    }
}

MyConfig.java

package com.config;

import com.aop.LogAop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan("com.service")
@Import(LogAop.class)
public class MyConfig {
    
    

}

MsgService.java

package com.service;

import org.springframework.stereotype.Component;

@Component
public class MsgService {
    
    
    public String ms(){
    
    
        System.out.println("ssss");
        return "1";
    }
}

Application.java

package com;

import com.config.MyConfig;
import com.service.MsgService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        MsgService msgService = applicationContext.getBean("msgService", MsgService.class);
        msgService.ms();
    }
}

执行结果:
在这里插入图片描述
这样我们的初步实现就出来了。
接下来我们使用运行通知(最终通知)和异常通知
在LogAop中添加代码

 @AfterReturning("logAop()")
 public void doAfterReturning(JoinPoint joinPoint){
    
    
     System.out.println("AfterReturning");
 }

 @AfterThrowing("logAop()")
 public void doAfterThrowing(JoinPoint joinPoint){
    
    
     System.out.println("AfterThrowing");
 }

运行结果:
在这里插入图片描述
这里可以看到After在AfterReturn之前,但是。博主原本使用的是springboot写的这篇文章,结果却是和spring中的结果不同,运行结果是这样的:
在这里插入图片描述
就很意外,最后通知和后置通知的位置反过来了,等理解为什么了,再来填坑吧。。
好了,我们继续填上面某个坑,大家会发现输出少了一个“AfterThrowing”,那我们怎么把它打印出来呢。
很简单,设置一个异常,他就出来了,更改MsgService.java

package com.service;

import org.springframework.stereotype.Component;

@Component
public class MsgService {
    
    
    public String ms(){
    
    
        System.out.println("ssss");
        int i = 1/0;
        return "1";
    }
}

运行出来了。。
在这里插入图片描述
我们会会发现,异常通知出来了,可是运行通知没有出来,这是因为他们两者并不共存。
上面的结果在springboot中,两者有时反过来的。。。 不纠结了,我们继续下一个重点内容
环绕通知
环绕通知很特别,它几乎可以做前后通知都可以做的事情
我们来看看怎么使用的吧,同样在LogAop.java增加代码

@Around("logAop()")
    public void doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
        System.out.println("环绕前");
        // 执行目标方法 
        joinPoint.proceed();
        System.out.println("环绕后");
    }

运行结果:
在这里插入图片描述
我们会发现,环绕前在前置通知之前,环绕后在后置通知之前,所以有时候可以代替他们两

猜你喜欢

转载自blog.csdn.net/weixin_43911969/article/details/114024729
今日推荐