前言
注解基础知识及使用示例
AOP基础知识点
博客地址:芒果橙的个人博客 【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:说明子类可以继承父类中的该注解
2.预置注解
- Deprecated:标识过时
- SuppressWarnings:忽略警告
二、使用
1.通过反射获取注解信息
- 对于属性字段注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
private String name;
private String value;
}
// field也是通过反射获取的
MyAnnotation ma = field.getAnnotation(MyAnnotation.class);
- Spring自定义接口参数校验注解 参考
示例:控制层接口方法参数校验
场景,提供的外部接口需校验传递参数的非空性
-
自定义注解
/** * @author * @date 2021/7/20 * @time 14:54 * @description 非空注解 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface MyNotNull { /** * 默认不为空 * @return */ boolean empty() default false; }
-
控制层切面
/** * @author * @date 2021/7/20 * @time 15:12 * @description 自定义控制层切面 */ @Component @Aspect public class MyControllerAspect { /** * 切线 */ private final String executeExpr = "execution(* com.mango.xx.web..*Controller.*(..))"; /** * 环绕通知(增强处理) * @param proceedingJoinPoint 切点 * @return * @throws IllegalAccessException */ @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; } /** * 解析注解 * @param arg 参数 * @return 提示信息;有值则校验不通过 */ 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; // ... }
三、前置知识-代理模式&AOP
1、代理模式
1.含义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用,通俗的来讲代理模式就是我们生活中常见的中介,动态代理和静态代理的区别在于静态代理我们需要手动的去实现目标对象的代理类,而动态代理可以在运行期间动态的生成代理类。
2.类别
- 静态代理:由开发人员创建或特定工具自动生成源代码,即在编译时就已经将接口、被代理类、代理类确定下来
- 动态代理:在程序运行时创建的代理方式
3.使用说明
- 代理模式最主要的就是有一个公共接口(Person),一个具体的类(Student),一个代理类(StudentsProxy),代理类持有具体类的实例,代为执行具体类实例方法
- 访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。这里的间接性就是指不直接调用实际对象的方法,那么我们在代理过程中就可以加上一些其他用途
2、基础
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框架为普通业务组织织入的处理动作
3、Spring AOP
Spring中的AOP代理和其依赖关系由Spring的IOC容器负责生成、管理
1.定义切入点和增强处理的方式
- 基于注解的“零配置”方式:使用@Aspect、@Pointcut等注解
- 基于XML配置文件:Spring配置文件
2.注解方式
- @Aspect – 作用是把当前类标识为一个切面供容器读取
- @Pointcut – (切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达
- @Before – 标识一个前置增强方法,相当于BeforeAdvice的功能
- @AfterReturning – 后置增强,相当于AfterReturningAdvice,方法退出时执行
- @AfterThrowing – 异常抛出增强,相当于ThrowsAdvice
- @After – final增强,不管是抛出异常或者正常退出都会执行
- @Around – 环绕增强,相当于MethodInterceptor