前情
这段时间想用AOP写个访问量功能,所以特地学习了一下AOP.记录一下AOP的使用方法。
AOP是什么
AOP (Aspect-oriented Program) ,面向切面编程。一般我们在使用OOP也就是面向对象编程的时候,我们的关注点在于一个完整的对象和另外一个完整对象之间的交互,而AOP的关注点在于对象的方法,也就是对象的行为。AOP就是用来增强对象的行为。换句话说,就是我希望对象在做出行为的时候,我需要给这个行为附加额外的行为,我们就可以使用AOP去实现这个功能。比如我们想要有人访问我接口的时候,我要先获取他的一些信息,那我们就可以使用AOP去实现。
使用方法
AOP实现可以有很多种方法,这里我记录一种,使用注解的方式。在spring boot中我们想要使用AOP就必须先添加对应依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
添加了依赖之后我们就可以使用啦。我们先定义一个AOP的类,在里面添加对应的切面和切点。
@Aspect
@Component
public class TextViewCountAspect {
private final Logger logger = LoggerFactory.getLogger(TextViewCountAspect.class);
@Autowired
private TxService txService;
//TODO 动态代理是什么?
//定义切入点 方法类型
@Pointcut("execution(public * com.honghu.wuqi.Controllers.TextController.getTextDetil(*))")
public void countTextView(){}
//定义切入点要增强的方法
@Before("countTextView()")
public void CountTextView(JoinPoint joinPoint){
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
//访问接口,增加访问量
txService.TextView((int)joinPoint.getArgs()[0],1);
// 记录下请求内容
logger.info("################URL : " + request.getRequestURL().toString());
logger.info("################HTTP_METHOD : " + request.getMethod());
logger.info("################IP : " + request.getRemoteHost());
logger.info("################IP : " + request.getRemoteAddr());
logger.info("################IP : " + request.getRemotePort());
logger.info("################THE ARGS OF THE CONTROLLER : " + Arrays.toString(joinPoint.getArgs()));
//下面这个getSignature().getDeclaringTypeName()是获取包+类名的 然后后面的joinPoint.getSignature.getName()获取了方法名
logger.info("################CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
}
}
首先,这个@Aspect注释告诉Spring这是个切面类,然后@Compoment将转换成Spring容器中的bean或者是代理bean。 总之要写切面这两个注解一起用就是了。
@PointCut
这个注解包含两部分,PointCut表达式和PointCut签名。表达式是拿来确定切入点的位置的,说白了就是通过一些规则来确定,哪些方法是要增强的,也就是要拦截哪些方法。
@PointCut(…)括号里面那些就是表达式。这里的execution是其中的一种匹配方式,还有:
execution: 匹配连接点
within: 某个类里面
this: 指定AOP代理类的类型
target:指定目标对象的类型
args: 指定参数的类型
bean:指定特定的bean名称,可以使用通配符(Spring自带的)
@target: 带有指定注解的类型
@args: 指定运行时传的参数带有指定的注解
@within: 匹配使用指定注解的类
@annotation:指定方法所应用的注解
关于表达式可以参考这个文章,写的很好。
https://www.cnblogs.com/wangshen31/p/9379197.html