首先声明一点,对于Spring来说我知道两大特性 Ioc和AOP,不过对于AOP以往都只是停留在知道,并没有在实际的工作中编写过对应的内容,因此在这篇文章中记录下编写的流程,各位大神就不用看了,我只是一个菜鸟。
这里主要记录的是通过标签的形式对Spring AOP的实现。
首先pom文件的编写,在dependencies标签中添加如下代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
之后编写一个简单的Controller代码(与正常的Controller一致,其中User是一个实体类,IUser是一个service接口)
package com.lxinyu.controller;
import com.lxinyu.entity.User;
import com.lxinyu.service.IUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by PC-Lxinyu on 2018/8/20.
*/
@RestController
public class TestController {
@Autowired
private IUser user;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public User login(){
System.out.println("111111111111");
return user.selectUser("aaa","abc");
}
}
然后,重要的来了,编写Aspect切面类
package com.lxinyu.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* Created by PC-Lxinyu on 2018/8/31.
*/
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(public * com.lxinyu.controller.*.*(..))")
public void controllerLog(){}
@Before("controllerLog()")
public void beforeLog(JoinPoint joinPoint){
System.out.println("function name is "+ joinPoint.getSignature().getName());
System.out.println("进入beforeLog");
}
}
在这个切面类中,用到了几个AOP中的关键内容,给大家说明一下:
- @Aspect标签: 该标签的作用是告诉Spring容器,这是一个切面类
- @Before标签: 该标签的作用是用来定义一个通知,通知定义了切面是什么以及何时调用
- @Pointcut标签: 该标签的作用是定义一个切点,通俗点的说就是什么时候可以进入到该切面类来执行对应的通知
- JoinPoint对象:JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象。这么说比较准确,但是也不是特别的容易理解,说一下我的理解,有不对的地方希望各位大神能够指出:“假设我在执行一个loginController之前,进入到了切面类中的这个通知,那这个joinPoint是不是就可以理解为是loginController对象”。这仅仅是我对于JoinPoint对象的理解,不是很准确,理解大概意思即可。
注:
- 通知有很多种,说一下常用的通知执行的时间:
- Before 在方法被调用之前调用通知
- After 在方法完成之后调用通知,无论方法执行是否成功
- After-returning 在方法成功执行之后调用通知
- After-throwing 在方法抛出异常后调用通知
- Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
- @PointCut标签的编写:
- execution函数用于匹配方法执行的连接点
- execution函数的语法为:execution(方法修饰符(可选) 返回类型 方法名 参数 异常模式(可选))
- 参数允许使用通配符
- * 匹配任意字符,但只能匹配一个元素
- .. 匹配任意字符,可以匹配任意多个元素,表示类时,必须和*联合使用
- + 必须跟在类名后面,如Horseman+,表示类本身和继承或扩展指定类的所有类
- 实例中的@PointCut所表示的意思是在com.lxinyu.controller包中所有类的所有public类型的方法都会进入到该切面类中执行对应的方法
- @Comonent标签必须编写,将其注入到Spring容器中!!!