一、首先先了解一下AOP
-
AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法,是对传统OOP(Programming,面向对象编程)的补充
- AOP的主要编程对象是切面(asspect),而切面模块化横切关注点。
- 在应用AOP编程时,仍需要定义公共功能,但可以明确的定义这个功能在哪里,以什么方式应用,并且不必修改受影响的类,这样一来横切关注点就被模块化到特殊对象(切面)里。
- AOP的好处:
每个事物逻辑位于一个位置,代码不分散,便于维护和升级。
业务模块更简洁,只包含核心业务代码。
5.AspectJ:Java社区里最完整最流行的AOP框架
6.在Spring2.0以上版本中,可以使用基于AspectJ注解或基于XML配置AOP
二、相关注解
1.Advice(通知、切面): 某个连接点所采用的处理逻辑,也就是向连接点注入的代码, AOP在特定的切入点上执行的增强处理。
1.1 @Before: 标识一个前置增强方法,相当于BeforeAdvice的功能.
1.2 @After: final增强,不管是抛出异常或者正常退出都会执行.
1.3 @AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行.
1.4 @AfterThrowing: 异常抛出增强,相当于ThrowsAdvice.
1.5 @Around: 环绕增强,相当于MethodInterceptor.
2.JointPoint(连接点):程序运行中的某个阶段点,比如方法的调用、异常的抛出等。
3.Pointcut(切入点): JoinPoint的集合,是程序中需要注入Advice的位置的集合,指明Advice要在什么样的条件下才能被触发,在程序中主要体现为书写切入点表达式。
由下列方式来定义或者通过 &&、 ||、 !、 的方式进行组合:
例:@Pointcut("execution(* com.savage.aop.MessageSender.*(..))")
- execution:用于匹配方法执行的连接点;
- within:用于匹配指定类型内的方法执行;
- this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
- target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
- args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
- @within:用于匹配所以持有指定注解类型内的方法;
- @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
- @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
- @annotation:用于匹配当前执行方法持有指定注解的方法;
4.Advisor(增强): 是PointCut和Advice的综合体,完整描述了一个advice将会在pointcut所定义的位置被触发。
5.@Aspect(切面): 通常是一个类的注解,里面可以定义切入点和通知
三、实际操作,切面参数验证
第一步:添加jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
第二步:自定义注解,用于切面参数验证:
package com.codebase.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Auther:wanglc
* @Date: 2020/3/2
* @Description:
* @Version:
*/
//@Target注解用于设定注解的使用范围
@Target({ElementType.METHOD})
//@Retention:作用是定义被它定义的注解保留多久,
@Retention(RetentionPolicy.RUNTIME)
public @interface AopInteValidator {
}
第二步:定义,切面验证数据格式
package com.codebase.aop;
import com.codebase.config.ResponseInfo;
import com.codebase.exception.FailedException;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.validation.*;
import java.util.*;
/**
* @Auther:wanglc
* @Date: 2020/3/2
* @Description:
* @Version:
*/
@Aspect
@Component
public class ValidatorAspect {
@Autowired
private Validator validator;
//定义一个方法,用于声明切入表达式。
@Pointcut("@annotation(com.codebase.aop.AopInteValidator)")
public void validatorPointcut() {
}
@Before("validatorPointcut()")
public void doBefore(JoinPoint joinPoint) {
{
boolean isHave = false;
Set<ConstraintViolation<Object>> violations = null;
List result = new ArrayList();
//取参数
List<Object> args = Arrays.asList(joinPoint.getArgs());
if(args.size()>0 && args != null){
violations = validator.validate(args.get(0));
List<String> mesList = new ArrayList<String>();
if (violations.size() > 0) {
isHave = true;
for (ConstraintViolation<Object> c : violations) {
mesList.add(c.getMessageTemplate());
}
result.add(mesList);
}
}
if (isHave) {
throw new FailedException(ResponseInfo.FORMAT_ERROR.getErrorCode(),
ResponseInfo.FORMAT_ERROR.getErrorMsg(),result);
}
}
}
}
package com.codebase.exception;
import com.codebase.config.ResponseInfo;
import java.util.List;
public class FailedException extends RuntimeException {
private int code;
private String messgae;
private List data;
public FailedException(String msg) {
this.code = ResponseInfo.UNKNOW_ERROR.getErrorCode();
this.messgae = msg;
}
public FailedException(int code, String msg) {
this.code = code;
this.messgae = msg;
}
public FailedException(int code, String msg, List data) {
this.code = code;
this.messgae = msg;
this.data=data;
}
public int getCode(){
return this.code;
}
public void setCode(int code){
this.code = code;
}
public String getMessgae() {
return messgae;
}
public List getData(){
return data;
}
}
package com.codebase.config;
public enum ResponseInfo {
SUCCESS(200,"SUCCESS"),
//用户认证异常
USERNAME_ERROR(1001,"用户名错误"),
USERNAME_EMPTY(1002,"用户名不能为空"),
PASSWORD_ERROR(1003,"密码错误"),
PASSWORD_EMPTY(1004,"密码不能为空"),
AUTH_FAILED(1005,"认证失败"),
//系统错误异常
UNKNOW_ERROR(8000, "未知错误"),
PARAM_ERROR(9000, "参数格式错误"),
FORMAT_ERROR(9001, "格式错误"),
SERVER_ERROR(9999, "服务器异常");
private int errorCode;
private String errorMessage;
ResponseInfo(int code, String msg) {
this.errorCode = code;
this.errorMessage = msg;
}
public int getErrorCode() {
return errorCode;
}
public String getErrorMsg() {
return errorMessage;
}
public static String getResponseErrorMsg(String code) {
for(ResponseInfo responseInfo: ResponseInfo.values()) {
if(code.equals(responseInfo.getErrorCode())) {
return responseInfo.getErrorMsg();
}
}
return SERVER_ERROR.getErrorMsg();
}
public static int getResponseErrorCode(String msg) {
if(msg == null) {
return UNKNOW_ERROR.getErrorCode();
}
for(ResponseInfo responseInfo: ResponseInfo.values()) {
if(msg.equals(responseInfo.getErrorMsg())) {
return responseInfo.getErrorCode();
}
}
return SERVER_ERROR.getErrorCode();
}
}
实体类
package com.codebase.bean;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* @Auther:wanglc
* @Date: 2020/3/2
* @Description:
* @Version:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@ApiModelProperty("姓名")
@NotEmpty(message ="name不能为空")
@Length(max = 10,message = "name长度不能超过10")
private String name;
@ApiModelProperty("邮箱")
@NotEmpty(message ="email不能为空")
@Length(max = 12,message = "email长度不能超过12")
private String email;
@ApiModelProperty("地址")
@NotEmpty(message ="addr不能为空")
@Length(max = 50,message = "addr长度不能超过50")
private String addr;
@ApiModelProperty("年龄")
@NotNull(message = "age不能为空")
private int age;
}