springboot-Java注解(Annotation)
Java注解
是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
注解相关类都包含在java.lang.annotation包(自己设的)中。
Java注解分类
JDK基本注解
@Override:
重写父类方法,与父类不同则报错
@Deprecated
用于指示某个程序元素(如类、方法、字段等)已经过时,不推荐使用。这个注解告诉开发者,这个元素可能会在未来的版本中被移除,建议使用其他替代方案。
@SuppressWarnings(value = "unchecked")
用于抑制编译器产生的警告。它允许开发者忽略特定的警告信息,从而避免编译输出被大量警告信息淹没。这个注解可以应用于类、方法、字段、构造函数和局部变量上。
JDK元注解
元注解用于修饰其他的注解(纪委:管干部的干部)
@Retention:定义注解的保留策略
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) //默认的保留策略,注解会在class字节码文件中存,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到
自定义注解
新建一个注解文件如下:
例子:
package com.zking.ssm.annotation;
import java.lang.annotation.*;
//该文件为自定义注解
//@Retention保留策略
@Retention(RetentionPolicy.RUNTIME)
//@Target:使用位置
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.PARAMETER})
//可以被文档收录
@Documented
public @interface Log {
//default 为设置默认值
String name() default "";
String title() default "";
String value() default "";
}
补充:
ElementType
枚举包括以下值:
TYPE
:类、接口(包括注解类型)或枚举声明。FIELD
:字段声明(包括枚举常量)。METHOD
:方法声明。PARAMETER
:参数声明。CONSTRUCTOR
:构造函数声明。LOCAL_VARIABLE
:局部变量声明。ANNOTATION_TYPE
:注解类型声明。PACKAGE
:包声明。TYPE_PARAMETER
:类型参数声明(自 Java 8 起)。TYPE_USE
:任何类型的使用(自 Java 8 起)。
使用:
package com.zking.ssm.service.impl;
import com.zking.ssm.annotation.Log;
import com.zking.ssm.service.Userservice;
//在@Target:使用位置标注的地方直接调用即可
@Log(name = "用户业务类")
public class UserserviceImpl implements Userservice {
//注当我们只给value赋值,则可以省略参数名
@Log(title = "根据id查询",name = "查询")
//@Override:重写父类方法,与父类不同则报错
@Override
public void findByid(@Log("参数") Integer id) {
}
}
解析注解(难点!!!)
方式一:创建注解处理器
前提具备反射的知识
例子:给@log添加注解功能意思为在调时输出他的信息:name,title,value
package com.zking.ssm.utill;
import com.zking.ssm.service.impl.UserserviceImpl;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception {
//java.lang.Class类--类的类
//编程时我们是面向jdbc中api编程的(jdbc-API):由orcal,sun公司提供
//然后当我们提供mysql驱动就可以操作MySQL(driver):产家
//例当我们要知道某个实现类中有某些方法时,我们第一步是得到类的类对象
//方式一:
Class c1 = Class.forName("com.zking.ssm.service.impl.UserserviceImpl");
//方式二:
Class c2 = UserserviceImpl.class;
//方式三:
UserserviceImpl userservice = new UserserviceImpl();
Class c3 = userservice.getClass();
//java.lang.reflect.Method
//getDeclaredMethods 是 Java 中 java.lang.Class 类的一个方法,
// 用于获取当前类声明的所有方法,包括公共(public)、受保护(protected)
// 、默认(包级私有)和私有(private)访问级别的方法,但不包括从父类继承的方法。
Method[] methods= c1.getDeclaredMethods();
for (Method m:methods){
System.out.println("输出UserserviceImpl方法名="+m.getName());
}
//调用方法
UserserviceImpl userservice2 = (UserserviceImpl) c1.newInstance();//得到实例
for (Method m:methods){
m.invoke(userservice2,1);
}
}
}
方式二:动态注解处理器(spring aop方式)
第一步pom文件导入依赖:
<properties> <!-- 版本指定--> <spring.version>5.3.24</spring.version> <junit5.version>5.8.2</junit5.version> </properties> <dependencies> <!-- 依赖导入--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <!--测试--> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit5.version}</version> <scope>test</scope> </dependency> </dependencies>
package com.zking.ssm.aop;
import com.zking.ssm.annotation.Log;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component//注入spring容器
@Aspect//声明当前类是一个切面类
public class LogAspect {
//@Pointcut:声明切入点
@Pointcut("@annotation(com.zking.ssm.annotation.Log)")
public void pointcut(){
}
//Before:前置通知
@Before("pointcut()")
//joinPoint:连接点
public void before(JoinPoint joinPoint) throws Exception{
System.out.println("before...");
//signature:签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//getMethod:获取代理中的方法,得不到注解信息
Method method = signature.getMethod();
//joinPoint.getTarget().getClass():获取目标对象
Method realMethod = joinPoint.getTarget().getClass()
.getDeclaredMethod(method.getName(),method.getParameterTypes());
Log log=realMethod.getAnnotation(Log.class);
if (log!=null){
System.out.println("log.name="+log.name()+",log.title="+log.title()+",log.value="+log.value());
}
}
}