我们知道aop它是一种面向切面编程的技术,它是基于动态代理实现的,在spring中就有两种实现方式,一种是基于based-schema方式实现的,还有一种是基于aspectj实现的,可以参考之前的博客Spring中aop的两种实现方式
有一个场景,当我们项目上线,上线之后出现了运行很慢的情况,这时候我想知道到底在那个环节出问题了,这时候我们就可以通过AOP来做了,可以通过打印日志来确定问题在哪一块,逐步排除,将代码动态的织入,解决问题之后移除掉就好,下面就来说说在spring boot中的aop是如何使用的
创建项目
可以发现在spring boot2.1.x版本中没有aop的相关依赖,这时我们先创建引入web依赖,创建完成在pom.xml文件中导入即可
在pom.xml文件中导入AOP的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
创建service
在service中是我们的业务方法,就是说在执行这里面的方法前后我们定义通知处理的话,查看是否是这一环节出了问题
package com.zhouym.springbootaop.service;
import org.springframework.stereotype.Service;
/**
* 〈〉
*
* @author zhouym
* @create 2019/9/6
* @since 1.0.0
*/
@Service
public class AopService {
public String getUserById(Integer id){
System.out.println("getUserById");
return "hello,goodmorning";
}
public void deleteUserById(Integer id){
System.out.println("deleteUserById");
}
}
创建controller
创建controller,通过接口访问,调用方法
package com.zhouym.springbootaop;
import com.zhouym.springbootaop.service.AopService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 〈〉
*
* @author zhouym
* @create 2019/9/6
* @since 1.0.0
*/
@RestController
public class AopController {
@Autowired
AopService aopService;
@GetMapping("/hello")
public String getUserById(Integer id){
return aopService.getUserById(id);
}
@DeleteMapping("/hello1")
public void deleteUserById(Integer id){
aopService.deleteUserById(id);
}
}
定义日志组件类
package com.zhouym.springbootaop;
import javafx.scene.chart.ValueAxis;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 〈日志组件类,打印日志信息〉
*
* @author zhouym
* @create 2019/9/6
* @since 1.0.0
*/
@Component //声明一个spring组件
@Aspect //表示这个类是一个切面类
public class LogComponent {
//指定切点入口,第一个*表示这个方法的返回值任意,在service包下面的所有类的所有方法,任意方法参数,这里如果我们要测具体的,可以将*换成具体的类名或者方法名,参数也可以指定
@Pointcut("execution(* com.zhouym.springbootaop.service.*.*(..))")
public void pc1() {
}
/**
*@Description 前置通知
*@Param [jp]
*@Return void
*@Author zhouym
*@Date 2019/9/6
*@Time 12:56
*/
@Before(value = "pc1()")
public void before(JoinPoint jp) {
String name = jp.getSignature().getName();
System.out.println("before----" + name);
}
/**
*@Description 后置通知
*@Param [jp]
*@Return void
*@Author zhouym
*@Date 2019/9/6
*@Time 12:56
*/
@After(value = "pc1()")
public void after(JoinPoint jp){
Signature signature = jp.getSignature();
String name = signature.getName();
System.out.println("after----"+name);
}
/**
*@Description 返回通知,这里用的Object参数接收,可以接收任意类型的返回参数
*@Param [jp, result]
*@Return void
*@Author zhouym
*@Date 2019/9/6
*@Time 12:54
*/
@AfterReturning(value = "pc1()",returning = "result")
public void afterReturning(JoinPoint jp,Object result){
String name = jp.getSignature().getName();
System.out.println("afterReturning-----"+name+"----"+result);
}
/**
*@Description 异常通知
*@Param [jp, e]
*@Return void
*@Author zhouym
*@Date 2019/9/6
*@Time 12:56
*/
@AfterThrowing(value = "pc1()",throwing = "e")
public void afterThrowing(JoinPoint jp,Exception e){
String name = jp.getSignature().getName();
System.out.println("afterThrowing----"+name+"-----"+e);
}
/**
*@Description 环绕通知
*@Param [pjp]
*@Return java.lang.Object
*@Author zhouym
*@Date 2019/9/6
*@Time 12:59
*/
@Around(value = "pc1()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// return pjp.proceed();
return "com.zhouym";
}
}
页面访问http://localhost:8080/hello,查看后台输出内容