注解基础知识及使用示例
博客地址:芒果橙的个人博客 【http://mangocheng.com】
含义:可以理解为标签,用以提示和赋予类或属性信息
一、基础 1. 元注解注解的注解,表明注解的信息
- @Target:规定注解可以用在哪里
- 取值:ElementType
- TYPE:类和接口
- FIELD:字段、枚举
- METHOD
- PARAMETER
- CONSTRUCTOR:构造
- LOCAL_VARIBLE:局部变量
- ANNOTATION_TYPE:注解
- PACKAGE:包
- 取值:ElementType
- @Retention:规定注解可以存在于哪里
- 取值:RetentionPolicy
- SOURCE:源代码
- CLASS:源代码、编译后的字节文件
- RUNTIME:源代码中、 编译以后的字节码文件中、 运行时内存中, 程序可以通过反射获取该注解
- 取值:RetentionPolicy
- document:说明该注解将被包含在javadoc中
- Inherited:说明子类可以继承父类中的该注解
- Deprecated:标识过时
- SuppressWarnings:忽略警告
- 对于属性字段注解
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation{ private String name; private String value; } // field也是通过反射获取的 MyAnnotation ma = field.getAnnotation(MyAnnotation.class);
- Spring自定义接口参数校验注解 参考
示例:控制层接口方法参数校验
场景,提供的外部接口需校验传递参数的非空性
-
自定义注解
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface MyNotNull { boolean empty() default false; }
-
控制层切面
@Component @Aspect public class MyControllerAspect { private final String executeExpr = "execution(* com.mango.xx.web..*Controller.*(..))"; @Around(executeExpr) public Object processLog(ProceedingJoinPoint proceedingJoinPoint) throws IllegalAccessException { // 方法 // Method method = ((MethodSignature)proceedingJoinPoint.getSignature()).getMethod(); // Class rc = method.getReturnType(); // 参数 Object[] args = proceedingJoinPoint.getArgs(); // 参数校验 for (Object arg : args) { // 参数校验 String msg = processArg(arg); if(!StringUtils.isEmpty(msg)){ ResultMessage resultMessage = new ResultMessage(); resultMessage.setSuccess(false); resultMessage.setCode(-1); resultMessage.setMsg(new StringBuilder(msg)); return resultMessage; } } // 方法名称 // String methodName = method.getName(); Object res = null; try { // 继续执行方法 res = proceedingJoinPoint.proceed(args); } catch (Throwable throwable) { throwable.printStackTrace(); } return res; } private String processArg(Object arg) throws IllegalAccessException { Field[] fields = arg.getClass().getDeclaredFields(); StringBuilder msg = new StringBuilder(); for (Field field : fields) { if(field.isAnnotationPresent(MyNotNull.class)){ field.setAccessible(true); MyNotNull annotation = field.getAnnotation(MyNotNull.class); boolean empty = annotation.empty(); Object value = field.get(arg); Class fieldType = field.getType(); if(fieldType == String.class){ if(!empty){ if(StringUtils.isEmpty(value)){ msg.append(field.getName() + " 不能为空"); msg.append(";"); } } } } } return msg.toString(); } }
-
使用注解
// 控制层方法 @PostMapping(value = "/loadLove") public Result loadLove(@RequestBody heartVO){ // ... return xx.loadLove(heartVO); } // 请求参数实体 public class heartVO { @MyNotNull private String truth; @MyNotNull private String heart; // ... }
1.含义:Aspect Oriented Programming编程范式,程序设计思想
2.目的:把通用逻辑从业务逻辑分离出来
3.常用术语
- Join point:拦截点,如某个业务方法
- Pointcut:Joinpoint的表达式,表示拦截哪些方法;一个P对应多个J
- Advice:要切入的逻辑,增强处理
- BeforeAdvice:在方法前切入
- AfterAdvice:在方法后切入
- AfterReturningAdvice:在方法返回后切入,抛出异常则不会切入
- AfterThrowingAdvice:在方法抛出异常时插入
- AroundAdvice:在方法执行前后切入,可以中断或忽略原有流程的执行
- Target Object:目标对象,被一个或多个切面通知的对象
- Weaving:织入,将切面应用到目标对象的过程
4.切面代码织入时机
- 编译期
- 类加载期
- 运行期
5.实现类别
- 静态AOP实现:AOP框架再编译阶段对程序进行修改,生成静态的AOP代理类。以AspectJ为代表
- 动态AOP实现:AOP框架在运行阶段动态生成AOP代理(实现对目标类的增强)。以Spring AOP为代表:jdk动态代理(实现接口)、cglib(继承)
6.实现内容
- 定义普通业务组件
- 定义切入点,一个切入点可以横切多个业务组件
- 定义增强处理,增强处理就是在AOP框架为普通业务组织织入的处理动作
参考:https://www.jianshu.com/p/9aed3fb454df
2、Spring AOPSpring中的AOP代理和其依赖关系由Spring的IOC容器负责生成、管理
1.定义切入点和增强处理的方式
- 基于注解的“零配置”方式:使用@Aspect、@Pointcut等注解
- 基于XML配置文件:Spring配置文件
2.注解方式
- @Aspect – 作用是把当前类标识为一个切面供容器读取
- @Pointcut – (切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达
- @Before – 标识一个前置增强方法,相当于BeforeAdvice的功能
- @AfterReturning – 后置增强,相当于AfterReturningAdvice,方法退出时执行
- @AfterThrowing – 异常抛出增强,相当于ThrowsAdvice
- @After – final增强,不管是抛出异常或者正常退出都会执行
- @Around – 环绕增强,相当于MethodInterceptor
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)