引入pom依赖
<dependency>
<groupId> org.aspectj</groupId >
<artifactId> aspectjweaver</artifactId >
<version> 1.8.8</version >
</dependency>
定义权限注解
package com.yidong.Aop;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
@Documented//说明该注解将被包含在javadoc中
@Retention(RetentionPolicy.RUNTIME)// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target({ElementType.METHOD, ElementType.PARAMETER})//@Target:定义注解的作用目标,方法和方法参数
@Inherited//说明子类可以继承父类中的该注解
public @interface SysLogin {
//登录用户名
public String username();
}
切入点表达式
表达式类型 | 说明 |
---|---|
execution | 定位到目标对象的方法上 |
within | 定位到具体的类型上 |
this | 代理对象的类型 |
target | 目标对象的类型 |
args | 参数的类型 |
@args | 传入的参数有被该注解修饰 |
@within | 类型修饰的注解 |
@annotation | 方法修饰的注解 |
execution表达式
语法: execution([访问权限类型] 返回值类型 [全限定类名] 方法名(参数名) [抛出的异常类型])
符合 | 含有 |
---|---|
* | 0到多个符合 |
… | 方法参数中表示任意个参数,用在报名后表示当前包及其子包 |
+ | 用在类名后表示当前类及其子类,用在接口后表接口及其实现 |
实例:
execution(public * *(. .))
指定切入点为:任意公共方法。
execution(* set *(. .))
指定切入点为:任何一个以“set”开始的方法。
execution(* com.xyz.service.*.*(. .))
指定切入点为:定义在service包里的任意类的任意方法。
execution(* com.xyz.service. .*.*(. .))
指定切入点为:定义在service包或者子包里的任意类的任意方法。“..”出现在类名中时,
后面必须跟“*”,表示包、子包下的所有类。
execution(* *.service.*.*(. .))
指定只有一级包下的serivce子包下所有类(接口)中的所有方法为切入点
execution(* *. .service.*.*(. .))
指定所有包下的serivce子包下所有类(接口)中的所有方法为切入点
通知类型
通知类型 | 说明 |
---|---|
前置通知 | 目标方法执行之前调用 |
后置通知 | 目标方法执行完成之后调用 |
环绕通知 | 目标方法执行前后都会调用方法,且能增强结果 |
异常处理通知 | 目标方法出现异常调用 |
最终通知 | 无论程序执行是否正常,该通知都会执行。类似于try…catch中finally代码块 |
定义切面
- 前置通知 @Before 在方法之前执行
- 后置通知 @After 在方法之后执行
- 异常通知 @AfterThrowing 方法出现异常时执行
- 最终通知 @AfterReturning 在方法返回后执行
- 环绕通知 @Around 在方法之前和之后执行(必须使用Object作为返回值类型) 定义入参ProceedingJoinPoint
point 表示连接点(使用该注解的方法对象)
下面方法是一个写死的登录拦截,当username为admin时有权限,其他就抛异常
package com.yidong.Aop;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
/**
* 前置通知 @Before 在方法之前执行
后置通知 @After 在方法之后执行
异常通知 @AfterThrowing 方法出现异常时执行
最终通知 @AfterReturning 在方法返回后执行
环绕通知 @Around 在方法之前和之后执行(必须使用Object作为返回值类型) 定义入参ProceedingJoinPoint point 表示连接点(使用该注解的方法对象)
* @author lWX1003892
*
*/
@Aspect
@Component
public class SysLoginAspect {
@Pointcut("@annotation(com.yidong.Aop.SysLogin)")
public void sysLogin() {
}
// @Before("sysLogin()")
// public void loginAspect(JoinPoint joinPoint) {
// System.out.println(joinPoint.getSignature().getName() + "收到的参数为" + Arrays.toString(joinPoint.getArgs()));
// }
@Around("sysLogin()")
public Object loginAround(ProceedingJoinPoint point) throws Throwable {
Signature signature = point.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
SysLogin login = method.getAnnotation(SysLogin.class);
if (login==null) {
return point.proceed();
}else {
System.out.println("login==="+login.username());
if (login.username().equals("admin")) {
return point.proceed();
}
throw new RuntimeException("没有权限");
}
}
}
测试controller
当注解中的参数为admin时登录成功 @SysLogin(username = “admin”),为其他参数时会抛异常
@SysLogin(username = "admin")
@RequestMapping("/findObj/crm/qryAop")
// @SuppressWarnings("unchecked")
public Map<String, Object> qryAop(@RequestBody Map<String,Object> map) {
//返回列表消息头
Map<String, Object> repMap = new HashMap<String, Object>();
repMap.put("code", "0");
return repMap;
}