AOP
AOP概念以及相关术语
概述
AOP(Aspect Oriented Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面 向对象编程的一种补充和完善,它以通过预编译方式和运行期动态代理方式实现在不修改源代码的情况 下给程序动态统一添加额外功能的一种技术。
相关注解
@Aspect :表明是一个切面类
@Before :前置通知,在方法执行之前执行
@After :后置通知,在方法执行之后执行
@AfterRuturning :返回通知,在方法返回结果之后执行
@AfterThrowing :异常通知,在方法抛出异常之后执行
@Around :环绕通知,围绕着方法执行
@Pointcut :切入点,PointCut(切入点)表达式有很多种,其中execution用于使用切面的连接点。
上面所提到的五种通知方法中,除了环绕通知外,其他的四个通知注解中,t通知方法加或者不加参数JoinPoint都可以,如果有用到JoinPoint的地方就加,用不到就可以不加。
JoinPoint:里包含了类名、被切面的方法名,参数等属性。
String name = joinPoint.getSignature().getName();//被切面的获取函数名
String args = Arrays.toString(joinPoint.getArgs());//获取参数
环绕通知:参数必须为ProceedingJoinPoint,pjp.proceed相应于执行被切面的方法。
@Around("log()")
public Object aroundMethod(ProceedingJoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
String args = Arrays.toString(joinPoint.getArgs());
Object result = null;
try {
System.out.println("环绕通知-->目标对象方法执行之前");
//目标对象(连接点)方法的执行
result = joinPoint.proceed();
System.out.println("环绕通知-->目标对象方法返回值之后");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("环绕通知-->目标对象方法出现异常时");
} finally {
System.out.println("环绕通知-->目标对象方法执行完毕");
}
return result;
}
}
返回通知:可以加returning = “XXX”,XXX即为被切入方法的返回值
@AfterReturning(value = "log()",returning = "result")
public void afterReturnLog(JoinPoint joinPoint ,Object result){
String name = joinPoint.getSignature().getName();
String args = Arrays.toString(joinPoint.getArgs());
System.out.println("Logger--->返回通知");
System.out.println(result);
}
异常通知:可以加throwing = “XXX”,供读取异常信息。
@AfterThrowing(value = "log()", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
String methodName = joinPoint.getSignature().getName();
System.out.println("Logger-->异常通知,方法名:"+methodName+",异常:"+ex);
}
返回通知和异常通知只会执行一个,如果产生异常,返回通知就不执行,后置通知一定会执行
环绕通知一般单独使用,环绕通知可以替代上面的四种通知
相关概念
通知:对被增强的方法进行增强的方法
切入点:被增强类的被增强方法
切入类:封装通知的类
通知的类型:前置通知,返回通知,异常通知,后置通知,环绕通知
前置通知:在被代理方法执行之前执行
返回通知:在被代理方法执行之后执行
异常通知:在被代理方法执行出错的时候执行
后置通知:无论怎样都会执行
代码
Controller类
@Controller
public class LogController {
@ResponseBody
@RequestMapping(value = "/register",method = RequestMethod.POST)
public String hello(User user){
if(!StringUtils.isEmpty(user.getUsername())){
return "login successs!";
}
return "login failed!";
}
}
User类
public class User {
private String username;
private String password;
public User() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
切面类Aspect
@Component
@Aspect
public class LogAspect {
//切入点:待增强的方法
@Pointcut("execution(* com.example.springbootaop.controller.*.*(..))")
//切入点签名
public void log(){
}
//前置通知
@Before("log()")
public void beforeLog(JoinPoint joinPoint){
//获取函数名
String name = joinPoint.getSignature().getName();
String args = Arrays.toString(joinPoint.getArgs());
System.out.println("Logger--->前置通知,参数信息:"+args);
}
//返回通知
@AfterReturning(value = "log()",returning = "result")
public void afterReturnLog(JoinPoint joinPoint ,Object result){
String name = joinPoint.getSignature().getName();
String args = Arrays.toString(joinPoint.getArgs());
System.out.println("Logger--->返回通知");
System.out.println(result);
}
}
请求页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录页</title>
</head>
<body>
<h2 align="center">登录页</h2>
<form th:action="@{/register}" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>