1、什么是注解?
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。它本身并不起任何作用,可以说有它没它都不影响程序的正常运行,注解的作用在于注解的处理程序,注解处理程序通过捕获被注解标记的代码然后进行一些处理,这就是注解工作的方式。
2、注解的作用?
知道了什么是注解,那么他的作用又是什么呢?
因为注解的不同,其作用也会大不一样,但是基本都是一下几点:
1、在编译时或程序执行时运行特定的方法
2、用来充当注释的作用(仅仅是一个文字的说明) 如@Deprecated表示已过期,不再建议使用
3、用来做代码的检测(验证) ,即检测此方法是否是一个重写的如@Override。
4、可以携带一些信息(内容) 比如以往我们可以使用文件.properties.xml注解来携带信息
3、注解注意事项
1、注解修饰只能是public 默认为public(即不写)
2、注解只支持 基本数据类型(int,byte,short,long,float,double,char,boolean)、String 、class、enum及以上的数组类型
4、元注解修饰自定义注解
1、@Target
ElementType.TYPE 应用于类、接口(包括注解类型)、枚举
ElementType.FIELD 应用于属性(包括枚举中的常量)
ElementType.METHOD 应用于方法
ElementType.PARAMETER 应用于方法的形参
ElementType.CONSTRUCTOR 应用于构造函数
ElementType.LOCAL_VARIABLE 应用于局部变量
ElementType.ANNOTATION_TYPE 应用于注解类型
ElementType.PACKAGE 应用于包
ElementType.TYPE_PARAMETER 1.8版本新增,应用于类型变量)
ElementType.TYPE_USE 1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)
2、@Retention
Java源文件阶段(RetentionPolicy.SOURCE);
编译到class文件阶段(RetentionPolicy.CLASS);
运行期阶段(RetentionPolicy.RUNTIME)。
3、@Inherited
使用该注解其@target类型只能为ElementType.TYPE,其含义使用该注解的注解,在修饰其他类时,他的子类也会自动继承这个注解。
4、@Repeatable
jdk1.8引入 ,表示被修饰的注解可以重复应用标注 ,需要定义注解和容器注解
5、@Documented
这个注解可以被javadoc工具解析,形成帮助文档
idea生成javadoc的方式:
顶行【Tools】-->【Generate javaDoc...】 -->
【选择输出路径】+【在Other command line arguments中添加[-encoding utf-8 -charset utf-8]】
5、注解的使用
1、创建自定义注解
@Target(ElementType.METHOD)//注解放置的目标位置即方法级别
@Retention(RetentionPolicy.RUNTIME)//注解在哪个阶段执行
@Documented
public @interface TestInterface {
// 操作模块
String operModul() default "";
// 操作类型
String operType() default "";
// 操作说明
String operDesc() default "";
}
2、结合AOP
首先创建一个AOP容器类 (PS: 使用@ASpect注解 需要提前导入AOP依赖)
@Aspect //标注该类是个aop容器
@Component //将该类注入到Spring容器中
public class TestAspect{
}
/**
* TestAspect
*
* @author NSB
*
*/
@Component
@Aspect
public class TestAspect {
//随便定义一个工具方法做切点用
@Pointcut("@annotation(com.xinpu.aop.TestInterface)")// 匹配持有该注解的方法
public void operLogPoinCut() {
}
/**
*
*
* @param joinPoint 方法的执行点
* @param result 方法返回值
* @throws Throwable
*/
//执行完operLogPoincut方法后执行
@AfterReturning(returning = "result", value = "operLogPoinCut()")
public void saveOperLog(JoinPoint joinPoint, Object result) throws Throwable {
//将返回值转换为map集合
Map<String,Object> map = (Map<String, Object>) JSONObject.toJSON(result);
map.forEach((x,y)-> System.out.println(map.get(x).toString()));
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
TestInterface annotation = method.getAnnotation(TestInterface.class);
//输出注解中参数的属性
System.out.println(annotation.toString());
}
}
PS: @Pointcut
-
execution():用于匹配方法执行的连接点
-
args(): 用于匹配当前执行的方法传入的参数为指定类型的执行方法
-
this(): 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
-
target(): 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
-
within(): 用于匹配指定类型内的方法执行;
-
@args():于匹配当前执行的方法传入的参数持有指定注解的执行;
-
@target():用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
-
@within():用于匹配所以持有指定注解类型内的方法;
-
@annotation:用于匹配当前执行方法持有指定注解的方法;
3、创建一个测试类
/**
* TestController
*
* @author NSB
*
*/
@RequestMapping("test")
@RestController
public class TestController {
@RequestMapping("testZJ")
@TestInterface(operModul="这是Modul",operType="这是Type",operDesc="这是Desc")
public Map<String,String> testZJ(){
Map<String,String> map = new HashMap();
map.put("这是key1","这是结果1");
map.put("这是key2","这是结果2");
return map;
}
}
运行postman看执行结果
INFOInitializing Spring DispatcherServlet 'dispatcherServlet'
INFOInitializing Servlet 'dispatcherServlet'
INFOCompleted initialization in 14 ms
这是结果1 //注解中map循环的输出 可以看出使用该注解在带偶用之后是可以获取到返回值的
这是结果2
//也是可以获取到自定义注解中三个参数的值
@com.xinpu.aop.TestInterface(operType=这是Type, operModul=这是Modul, operDesc=这是Desc)
通过以上可以发现,我们可以轻松的获取到返回值,并且可以在方法中随便写自己想要执行的逻辑,那么只需要把方法内的逻辑改变成往数据库插入你想要的参数就可以轻松的实现包括操作记录在内的多种功能。
OK,本次分享到此就结束了,码字不易感谢三连支持!!!
有什么疑问的话,可以在评论区提问,看到的话会第一时间回答。