说过IOC,就接着说一下AOP吧。AOP是个啥?IOC是控制反转,将Bean的初始化交给Spring容器,然后通过DI依赖注入到程序中,那AOP是干嘛的?它有没有什么类似DI的方法?
AOP
AOP 是 Aspect Oriented Programming 的缩写,翻译为:面向切面编程
所以切面是什么意思?理解了切面,我们才是真正的理解了AOP。
在实现业务的时候,每个接口都会做用户是否被禁用校验,这段代码很简单,可能也就是两行代码,但是每个方法都写一遍也太麻烦了。
- 想法一:抽出一个公共方法,在每次调用接口时调用一下。是,简单了一点,但是觉得还是麻烦。
- 想法二:在拦截器里面做?等等。。过滤器,拦截器,aop。怎么感觉都差不多?三者区别?以后再说。不在过滤器,拦截器里面做处理的原因是涉及到业务逻辑,前二者粒度太粗了,都是从request里面获取数据操作。
- 想法三:利用AOP实现。
所以AOP可以帮助我们干啥?
- 参数匹配和校验
- 安全控制
- 日志记录
- 埋点
- 性能处理
- 等…
AOP术语
刚才说道AOP里面有个关键词叫:切面,其实不止有切面,还有好多关键词。。
- 连接点(Joinpoint):在程序执行过程中某个特定的点,比如类开始初始化前、类初始化后、类的某个方法调用前/后。在Spring AOP中,一个连接点总是表示一个方法的执行。
- 切点(Pointcut):每个类中都有多个连接点,AOP通过"切点"定个位特性的连接点。一个切点可以匹配多个连接点。
- 增强 - 通知(Advice):增强是织入目标连接点上的一段程序代码。同时还拥有另一个和连接点相关的信息,是执行点的方位。
- 目标对象(Target):目标对象就是我们需要对它进行增强的业务类~
- 织入(Weaving):织入就是将增强添加到目标类具体连接点上的过程。
- 代理(Proxy):一个类被AOP织入增强后,就产生了一个结果类,他是融合了原类和增强逻辑的代理类。
- 切面(Aspect):切面由切点和增强(或引介)组成,或者只由增强(或引介)实现。
AOP示例
package com.study.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
@Aspect
@Configuration
public class TestAop {
final AtomicInteger atomicInteger = new AtomicInteger();
/**
* 定义一个切入点
*/
@Pointcut("execution(* com.study.spring_cloud.controller.HelloController.*(..))")
public void webLog() {
System.out.println("我又被调用了。" + atomicInteger.incrementAndGet());
}
@Before("webLog()")
public void deBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
System.out.println("URL : " + request.getRequestURL().toString());
System.out.println("HTTP_METHOD : " + request.getMethod());
System.out.println("IP : " + request.getRemoteAddr());
System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
System.out.println("方法的返回值 : " + ret);
}
/**
* 后置异常通知
*/
@AfterThrowing("webLog()")
public void throwss(JoinPoint jp) {
System.out.println("方法异常时执行.....");
}
/**
* 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
*/
@After("webLog()")
public void after(JoinPoint jp) {
System.out.println("方法最后执行.....");
}
/**
* 环绕通知,环绕增强,相当于MethodInterceptor
*/
@Around("webLog()")
public Object arround(ProceedingJoinPoint pjp) {
System.out.println("方法环绕start.....");
try {
Object o = pjp.proceed();
System.out.println("方法环绕proceed,结果是 :" + o);
return o;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
}