<!-- 版本号随parent中的pom.xml文件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
主要有@Target,@Retention,@Document,@Inherited用来修饰注解。
表明该注解的生命周期,在开发过程中99%使用的是RetentionPolicy.RUNTIME
表明该注解标记的元素可以被Javadoc 或类似的工具文档化
表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解
/**
* @author Administrator
* @Documented –注解是否将包含在JavaDoc中
* @Retention –什么时候使用该注解
* @Target –注解用于什么地方
* @Inherited – 是否允许子类继承该注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
}
@Pointcut
定义切入点,可批量设置,也可单个方法设置,同时支持多个表达式使用&&(且),||(或)连接
execution(* * *):三个参数含义:
@Before
在被代理对象的方法前先调用。简单的说在方法执行之前,执行该方法
@After
在被代理对象的方法后调用。简单的说在方法执行之后,return之前执行该方法
@AfterReturning
在被代理对象的方法正常返回后调用,简单的说在方法执行之后,return之后执行该方法
@Around
将被代理对象的方法封装起来,用环绕通知取代他,简单的说执行两次,该方法必须执行
joinPoint.proceed();表示执行目标方法
// 各个注解执行周期如下
@Before
@Around (joinPoint.proceed)之前
执行目标方法(即切入点方法)
@Around (joinPoint.proceed)之后
@After
@AfterReturning
@AfterThrowing
在被代理对象的方法抛出异常后调用,简单的说执行的方法抛任何异常,执行切面方法
切入点定义举例介绍
@Pointcut(“execution(public * com.xxx.xxx.TestController.*(…)) && @annotation(com.test.my.annotation.OperationLog )” ) || execution(public * com.xxx.xxx.Controller.(…))
说明:在包com.xxx.xxx.TestController.java下的所有public方法且方法需要标注@OperationLog或者是com.xxx.xxx包下后缀为Controller.java的所有方法定义为切入点
方法 | 描述 |
---|---|
Signature getSignature(); | 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 |
Object[] getArgs(); | 获取传入目标方法的参数对象 |
Object getTarget(); | 获取被代理的对象 |
Object getThis(); | 获取代理对象 |
方法 | 描述 |
---|---|
Signature getSignature(); | 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 |
Object[] getArgs(); | 获取传入目标方法的参数对象 |
Object getTarget(); | 获取被代理的对象 |
Object getThis(); | 获取代理对象 |
Object proceed() | 执行目标方法 |
Object proceed(Object[] newArgs) | 传入的新的参数去执行目标方法 |
本次使用案例,MyBatis分页查询,自动注入分页参数功能
添加分页查询依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
/**
* @author
* 分页插件自定义注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AnnPageHelper {
/**
* 第几页
* @return
*/
int pageNum() default 1;
/**
* 每页条数
* 默认20
* @return
*/
int pageSize() default 20;
}
核心分为三个步骤
/**
* @author Administrator
* 日志操作切面具体逻辑
* order的值越小,优先级越高,默认值Integer.MAX
*/
@Aspect
@Order(-1)
@Component
public class PageHelperAspect {
public static final Logger logger = LoggerFactory.getLogger(PageHelperAspect.class);
// 定义切入点,在对象或者是方法上标注@AnnPageHelper为切入点
@Pointcut("@annotation(com.sifisense.annotation.AnnPageHelper) || @within(com.sifisense.annotation.AnnPageHelper)")
public void cutLog(){};
// 指定切入点需要执行的周期
// @Before("cutLog()") 方式一
// @Before("@annotation(pageHelper) || @within(pageHelper)") 方式2
@Before("cutLog()")
public void before(JoinPoint point, AnnPageHelper pageHelper){
setPageHelper(point, pageHelper);
}
/**
* 切面执行的方法,设置分页查询参数
* @param joinPoint
* @param pageHelper
*/
public void setPageHelper(JoinPoint joinPoint, AnnPageHelper pageHelper) {
logger.info("目标方法名为:" + joinPoint.getSignature().getName());
logger.info("目标方法所属类的简单类名:" + joinPoint.getSignature().getDeclaringType().getSimpleName());
logger.info("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
logger.info("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
logger.info("被代理的对象:" + joinPoint.getTarget());
logger.info("代理对象自己:" + joinPoint.getThis());
BaseRequest request = null;
//获取传入目标方法的参数
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
if(args[i] instanceof BaseRequest) {
request = (BaseRequest) args[i];
break;
}
}
if(null != request) {
// 参数1:第几页索引从1开始,参数2:每页几条
PageHelper.startPage(request.getPageNum(), request.getPageSize());
} else {
PageHelper.startPage(pageHelper.pageNum(), pageHelper.pageSize());
}
}
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private TbUserMapperExt tbUserMapperExt;
@AnnPageHelper
@Override
public List<TbUser> findPager(BaseRequest request) {
return tbUserMapperExt.selectByExample(new TbUserExample());
}
}
@Test
public void test() {
BaseRequest baseRequest = new BaseRequest();
// 第二页,期望结果limit 5,5
baseRequest.setPageNum(2);
// 每页5条
baseRequest.setPageSize(5);
userService.findPager(baseRequest);
}