java注解详情及自定义注解和使用场景
- 注解概念
- jdk预定义的注解
- jdk提供了4个元注解
- JDK中给我们提供的4个元注解
- 1.@Target:描述当前注解能够作用的位置
- 2.@Retention: 描述注解被保留到的阶段
- 3.@Documented:描述注解是否被抽取到JavaDoc api中
- 4.@inherited:描述注解是否可以被子类继承
- 自定义注解
- 注解的样式
- 注解的本质
- 自定义注解
- 自定义注解
- 定义studnet1类
- 测试
- 注解应用场景
- 场景一:自定义注解+拦截器 实现登录校验
- 场景二:自定义注解+AOP 实现接口执行时间打印
注解概念
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
jdk预定义的注解
@Override:检查被该注解标注的方式是否是继承自父类【接口】
@Deprecated: 该注解表示注释的内容过时
@SuppressWarnings: 压制警告
jdk提供了4个元注解
JDK中给我们提供的4个元注解
1.@Target:描述当前注解能够作用的位置
ElementType.TYPE:可以作用在类上
ElementType.METHOD:可以作用在方法上
ElementType.FIELD:可以作用在成员变量上
2.@Retention: 描述注解被保留到的阶段
SOURCE < CLASS < RUNTIME
SOURCE:表示当前注解只在代码阶段有效
CLASS:表示该注解会被保留到字节码阶段
RUNTIME:表示该注解会被保留到运行阶段 JVM
自定义的注解:RetentionPolicy.RUNTIME
3.@Documented:描述注解是否被抽取到JavaDoc api中
4.@inherited:描述注解是否可以被子类继承
自定义注解
注解的样式
// 元注解
public @interface 注解名称{
// 属性列表
}
注解的本质
在对该注解类的class文件进行反编译时,发现注解的本质是接口,并继承java.lang.annotation.Annotation
自定义注解
了解本质后,我们来进行自定义注解的讲解
自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InvokAnno {
String className();
String methodName();
}定义studnet1类
public class Student1 {
public void show(){
System.out.println(“student1 show …”);
}
}测试
@InvokAnno(className = “com.gupao.edu.anno2.Student2”,methodName = “show”)
public class MyMain {
public static void main(String[] args) throws Exception {
// 获取类对象
Class clazz = MyMain.class;
// 获取类对象中的注解
InvokAnno an = clazz.getAnnotation(InvokAnno.class);
/**• 注解本质是 接口 获取到的其实是接口的实现
• public class MyInvokAnno implements InvokAnno{
•
• String className(){
• return “com.gupao.edu.anno2.Student1”;
• }
• String methodName(){
• return “show”;
• }
• }
*/
// 获取注解中对应的属性
String className = an.className();
String methodName = an.methodName();
System.out.println(className);
System.out.println(methodName);// 通过反射的方式实现接口的功能
Class<?> aClass = Class.forName(className);
Method show = aClass.getDeclaredMethod(“show”);
// 方法的执行
Object o = aClass.newInstance();
show.invoke(o); // 执行对应的方法
}
}
注解应用场景
场景一:自定义注解+拦截器 实现登录校验
1.手写注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginAnnotaion {
}2.拦截器
@Configuration
public class WebMvcConfigurerTest implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor()).addPathPatterns("/").excludePathPatterns("/js/","/css/","/images/");
}
}public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(“拦截了”);
HandlerMethod handlerMethod=(HandlerMethod)handler;
//获取拦截的方法
LoginAnnotaion loginAnnotaion=handlerMethod.getMethod().getAnnotation(LoginAnnotaion.class);
//该方法有这个注解,放行,不拦截
if(loginAnnotaion!=null){
return true;
}
response.setContentType(“application/json; charset=utf-8”);
response.getWriter().print(“你访问的资源需要先登录”);
return false;
}@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}3.controller
@RestController
public class TestController {//放开
@LoginAnnotaion
@GetMapping("/way/{id}")
public String way(@PathVariable(“id”) Integer id){
return id.toString()+“way”;
}@GetMapping("/way2/{id}")
public String way2(@PathVariable(“id”) Integer id){
return id.toString()+“way2”;
}
}
场景二:自定义注解+AOP 实现接口执行时间打印
先导入切面和lombok需要的依赖包
org.springframework.boot
spring-boot-starter-aop
org.projectlombok
lombok
true定义一个注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AopAnnotation {
}写一个aop
@Aspect
@Component
@Slf4j
public class LogAspect {@Pointcut(value = “@within(com.example.loginrequireannotation.annotation.AopAnnotation) || @annotation(com.example.loginrequireannotation.annotation.AopAnnotation)”)
public void logPointCut(){
}// 3. 环绕通知
3.controller
@AopAnnotation
@RestController
public class AopController {@LoginAnnotaion
@GetMapping("/user/{id}")
public String way(@PathVariable(“id”) Integer id){
return id.toString()+“user”;
}
@Around(value = "logPointCut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("====== 开始执行 {}.{} ======",
joinPoint.getTarget().getClass(),
joinPoint.getSignature().getName());
// 记录开始时间
long begin = System.currentTimeMillis();
// 执行目标 service
Object result = joinPoint.proceed();
// 记录结束时间
long end = System.currentTimeMillis();
long takeTime = end - begin;
if (takeTime > 3000) {
log.error("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
} else if (takeTime > 2000) {
log.warn("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
} else {
log.info("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
}
return result;
}
}
@LoginAnnotaion
@GetMapping("/teacher/{id}")
public String way2(@PathVariable(“id”) Integer id){
return id.toString()+“teacher”;
}
}