什么是注解(Annotation):
**Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。**Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。
1、生成文档。这是最常见的,也是java 最早提供的注解。常用的有@param @return 等
2、跟踪代码依赖性,实现替代配置文件功能。比如Spring的注入,未来java开发,将大量注解配置,具有很大用处; 后期学习框架大量使用, 基于注解的开发
3、在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出
jdk定义好这个注解的声明, 开发者直接使用, 语法检查
@SuppressWarnings("all")
public class Demo1 {
@SuppressWarnings("all")
public void fun1(){
System.out.println("dddd");
}
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
demo2.fun1(10);
Date d = new Date();
//2022 - 1970 = 52 1900 ~ 1999
System.out.println(d.getYear()); //2022 122
}
}
@SuppressWarnings("all")
class Demo2 extends Demo1{
//重写Demo1的
//@Override
/**
* @param a 声明了方法参数
* @return 声明方法返回值
*/
@Deprecated
public int fun1(int a){
return 1;
}
}
jdk定义好这个注解的声明, 在注解上使用
@Documented-注解是否将包含在JavaDoc中
@Retention –什么时候使用该注解
Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间
它的取值如下:
- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
自定义注解: 保留期一定设置为runtime
@Target–注解用于什么地方
默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
@Inherited – 定义该注释和子类的关系
Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解
定义两种注解及使用方式
@Target(ElementType.TYPE)//表明该自定义注解能应用到什么位置
@Retention(RetentionPolicy.RUNTIME)//表明该注解能存活到什么时候
public @interface MyAnnotation {//注解体为空,表明该自定义注解是一个标记注解
}
使用该注解:
@MyAnnotation
@Target(ElementType.TYPE)//表明该自定义注解能应用到什么位置
@Retention(RetentionPolicy.RUNTIME)//表明该注解能存活到什么时候
public @interface MyAnnotation {
//包含了成员变量的注解称为元数据注解
String name();//注解中定义成员变量后要加()
int age();
//成员变量的访问权限只能是public或缺省,不能是private或protected
}
使用注解:
@MyAnnotation(name="abss",age=19)//元数据注解要给成员变量赋值
设置默认初值
@Target(ElementType.TYPE)//表明该自定义注解能应用到什么位置
@Retention(RetentionPolicy.RUNTIME)//表明该注解能存活到什么时候
public @interface MyAnnotation {//注解体为空,表明该自定义注解是一个标记注解
String name() default "张三";//注解中定义成员变量后要加()
int age() default 20;//包含了成员变量的注解称为元数据注解
//成员变量的访问权限只能是public或缺省,不能是private或protected
}
@MyAnnotation//元数据注解可以不给成员变量赋值
@Target参数不同使用的地方不同
@Target(ElementType.METHOD)//表明该自定义注解能应用到什么位置-----------------------方法
@Retention(RetentionPolicy.RUNTIME)//表明该注解能存活到什么时候
public @interface MyAnnotation {//注解体为空,表明该自定义注解是一个标记注解
String name() default "张三";//注解中定义成员变量后要加()
int age() default 20;//包含了成员变量的注解称为元数据注解
//成员变量的访问权限只能是public或缺省,不能是private或protected
}
public class Student implements Serializable {
//不定义序列化id会有警告
//private static final long serialVersionID= 1L;
@SuppressWarnings("rawtypes")
public List list=new ArrayList();//没有启用泛型机制警告
@Override
@MyAnnotation(name="s",age=19)元数据注解要给成员变量赋值-------------------方法
public String toString(){
return "";
}
@Deprecated
public void play(){}
}
@Target(ElementType.FIELD)//表明该自定义注解能应用到什么位置------------------------字段
@Retention(RetentionPolicy.RUNTIME)//表明该注解能存活到什么时候
public @interface MyAnnotation {//注解体为空,表明该自定义注解是一个标记注解
String name() default "张三";//注解中定义成员变量后要加()
int age() default 20;//包含了成员变量的注解称为元数据注解
//成员变量的访问权限只能是public或缺省,不能是private或protected
}
@SuppressWarnings("serial")
public class Student implements Serializable {
//不定义序列化id会有警告
//private static final long serialVersionID= 1L;
@SuppressWarnings("rawtypes")
@MyAnnotation(name="s",age=19)//元数据注解要给成员变量赋值---------------------字段
public List list=new ArrayList();//没有启用泛型机制警告
@Override
public String toString(){
return "";
}
@Deprecated
public void play(){}
}
@Target(ElementType.CONSTRUCTOR)//表明该自定义注解能应用到什么位置---------------构造方法
@Retention(RetentionPolicy.RUNTIME)//表明该注解能存活到什么时候
public @interface MyAnnotation {//注解体为空,表明该自定义注解是一个标记注解
String name() default "张三";//注解中定义成员变量后要加()
int age() default 20;//包含了成员变量的注解称为元数据注解
//成员变量的访问权限只能是public或缺省,不能是private或protected
}
public class Student implements Serializable {
//不定义序列化id会有警告
//private static final long serialVersionID= 1L;
@SuppressWarnings("rawtypes")
private String name;
private int age;
public List list=new ArrayList();//没有启用泛型机制警告
@Override
public String toString(){
return "";
}
@Deprecated
public void play(){}
@MyAnnotation(name="s",age=19)//元数据注解要给成员变量赋值------------------构造方法
public Student(){super();}
@MyAnnotation(name="s",age=19)//元数据注解要给成员变量赋值------------------构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
@Target(ElementType.PARAMETER)//表明该自定义注解能应用到什么位置-----------------方法参数
@Retention(RetentionPolicy.RUNTIME)//表明该注解能存活到什么时候
public @interface MyAnnotation {//注解体为空,表明该自定义注解是一个标记注解
String name() default "张三";//注解中定义成员变量后要加()
int age() default 20;//包含了成员变量的注解称为元数据注解
//成员变量的访问权限只能是public或缺省,不能是private或protected
}
public class Student implements Serializable {
//不定义序列化id会有警告
//private static final long serialVersionID= 1L;
@SuppressWarnings("rawtypes")
private String name;
private int age;
public List list=new ArrayList();//没有启用泛型机制警告
public void study(@MyAnnotation(name="s",age=19)String type){}//-------方法参数
}
通过反射读取注解信息-1
@Target(ElementType.TYPE)//表明该自定义注解能应用到什么位置
@Retention(RetentionPolicy.CLASS)//表明该注解能存活到什么时候
//如果要通过反射读取注解信息,自定义函数的生存周期必须是
public @interface MyAnnotation2 {}
public class test {
public static void main(String[] args) {
//反射的基础是Class对象
Annotation annos[]=Student.class.getAnnotations();//获取一个类中添加的所有的自定义注解
for (Annotation an:annos)
System.out.println(an);
}
}
//输出
@cn.edu.xync.ssm.annotation.MyAnnotation(name=张三, age=20)
@cn.edu.xync.ssm.annotation.MyAnnotation2()
通过反射读取注解信息-2
@SuppressWarnings("serial")
@MyAnnotation//元数据注解要给成员变量赋值
public class Student implements Serializable {
@Deprecated
@MyAnnotation2
public void study(String type){}
@MyAnnotation2
public void work(){}
}
@Target(ElementType.METHOD)//表明该自定义注解能应用到什么位置
@Retention(RetentionPolicy.CLASS)//表明该注解能存活到什么时候
public @interface MyAnnotation2 {
}
@Test
public void test(){
//反射的基础时Class对象
Annotation annos[]=Student.class.getAnnotations();//获取一个类中添加的所有自定义注解
for (Annotation an:annos)
System.out.println(an);
}
Method methods[]=Student.class.getDeclaredMethods();
for (Method method:methods)
{
if (method.isAnnotationPresent(MyAnnotation.class)){//判断方法上是否添加了某个自定义注解类的注解
System.out.println(method.getName()+"方法上添加了MyAnnotation注解");
}
通过反射读取注解信息-3
Annotation anno=Student.class.getAnnotation(MyAnnotation.class);//获取一个类中添加的所有自定义注解
if (anno!=null){
MyAnnotation myAnnotation=(MyAnnotation) anno;
try {
Student student=Student.class.newInstance();
System.out.println("赋值之前----"+student.toString());
Method method1=Student.class.getDeclaredMethod("setName",String.class);
method1.invoke(student,myAnnotation.name());
Method method2=Student.class.getDeclaredMethod("setAge",int.class);
method2.invoke(student,myAnnotation.age());
System.out.println("赋值之后----"+student.toString());
} catch (InstantiationException e) { e.printStackTrace();
} catch (IllegalAccessException e) { e.printStackTrace();
} catch (NoSuchMethodException e) { e.printStackTrace();
} catch (InvocationTargetException e) { e.printStackTrace(); }
----------
public @interface MyAnnotation {//注解体为空,表明该自定义注解是一个标记注解
String name() default "张三";//注解中定义成员变量后要加()
int age() default 20;//包含了成员变量的注解称为元数据注解
//成员变量的访问权限只能是public或缺省,不能是private或protected
注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池
这个运行时生成的动态代理对象是可以导出到文件的,方法有两种
@DataAuth(spaceName = "#space")
@PostMapping("/list")
@ApiOperation("卡片展示列表(图谱详情)")
public R<List<DetailSpace>> detailSpace(@RequestBody GraphShowAttribute graphShowAttribute, @PathVariable String space) {
return R.data(spaceService.detailSpace(graphShowAttribute));
}
如果是单个参数,@DataAuth(spaceName = “#space”)
如果是对象参数,@DataAuth(spaceName = “#graphShowAttribute.space”)
他是project lombok库的一部分。project lombok是一个java库,旨在减少样板代码和提高代码的可读性。
@UtilityClass注解用于创建一个具有静态方法的实用工具类,而无需显示编写类的构造函数或将类声明为final。
这个注解通常用于声明不可实例化的工具类。
@Lombok会在编译时自动生成一些常见的实用方法,如静态工厂方法、静态常量等。
类被@UtilityClass注解标记后,其构造函数会被声明为私有,并且不允许实例化该类。
所有方法都被声明为static,因此您可以直接用过类名称来调用这些方法,而不需要创建类的实例。
常见的实用方法,如:toString(), hashCode(), equals(), 以及一些 静态常量的生成都会由lombok自动生成。
示例:
import lombok.experimental.UtilityClass;
@UtilityClass
public class MathUtils {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
}
在上面的示例中,MathUtils 类被标记为 @UtilityClass,它包含了两个静态方法 add 和 subtract。这些方法可以直接通过类名称调用,而不需要创建 MathUtils 的实例。
@UtilityClass 适用于具有纯粹静态方法和常量的实用工具类。
可以用于替代常见的实用类,如 java.lang.Math,java.util.Collections 等,使代码更易读和维护。
避免了手动编写构造函数、静态工厂方法以及常量定义,减少了样板代码。
Lombok 配置:
使用 @UtilityClass 需要确保 Lombok 插件已添加到项目的构建工具中(例如,Maven 或 Gradle),并且IDE(如 IntelliJ IDEA)已正确配置以支持 Lombok 注解。
总之,@UtilityClass 注解是 Lombok 提供的一个方便工具,用于生成实用工具类,减少代码冗余,提高代码可读性,并促进静态方法的使用。
EnableAutoConfiguration自动装配的作用:即把指定的类构造成对象,并放入spring容器中,使其成为bean对象,作用类似@Bean注解。
springboot启动的时候,会扫描该项目下所有spring.factories文件
参考地址
**作用:**用于将对象存入spring的容器中,同@Controller、@Service、@Component、@Configuration、@Repository等几个注解是一样的,都是负责将对象存入容器中,只不过方式不同,他们都是用在类上面,然后由当前类通过无参构造函数创建对象然后放入容器,而@Bean则是用在方法上,将当前方法返回值对象放到容器中,可以理解为前者是spring自动创建对象,后者则是我们手动创建的。
说明该注解将被包含在javadoc中
@Documented是元注解
// 生成 java doc 的命令:
javadoc -d doc TerminalController.java`
// -d <directory> 输出文件的目标目录
@Import注解提供了三种用法
1、@Import一个普通类 spring会将该类加载到spring容器中
2、@Import一个类,该类实现了ImportBeanDefinitionRegistrar接口,在重写的registerBeanDefinitions方法里面,能拿到BeanDefinitionRegistry bd的注册器,能手工往beanDefinitionMap中注册 beanDefinition
3、@Import一个类 该类实现了ImportSelector 重写selectImports方法该方法返回了String[]数组的对象,数组里面的类都会注入到spring容器当中
1)在方法上使用该@Async注解,申明该方法是一个异步任务;
2)在类上面使用该@Async注解,申明该类中的所有方法都是异步任务;
3)方法上一旦标记了这个@Async注解,当其它线程调用这个方法时,就会开启一个新的子线程去异步处理该业务逻辑。
4)使用此注解的方法的类对象,必须是spring管理下的bean对象;
5)要想使用异步任务,需要在主类上开启异步配置,即配置上@EnableAsync注解;
注解的作用目标
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包
用于指定注解的保留策略,既注解的生命周期。该注解可以用于自定义注解上,指定该注解可以保留多长时间。
@Retention 注解包含一个RetentionPolicy类型的属性value,用于指定注解的保留策略,常用的保留策略包括:
RetentionPolicy.SOURCE:表示注解仅在源代码中保留,编译器编译时将其忽略,不会保存在编译后的字节码中。
RetentionPolicy.CLASS:表示注解在编译后的字节码中保留,但在运行时不会加载到JVM这是默认的保留策略
RetentionPolicy.RUNTIME:表示注解在编译后的字节码中保留,并在运行时被加载到JVM中。可以使用反射机制来访问该注解。
示例:
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
// ...
}
说明子类可以继承父类中的该注解
被 @Inherited 注解修饰的注解,如果作用于某个类上,其子类是可以继承的该注解的。反之,如果一个注解没有被 @Inherited注解所修饰,那么他的作用范围只能是当前类,其子类是不能被继承的。
@AliasFor是Spring框架的一个注解,用于声明注解属性的别名。它有两种不同的应用场景。
这时@MyAnnotationB(“vvv”)就和@MyAnnotationA(a2=“vvv”)等价。
两者主要的区别在于是否在同一个注解内。
这种用法有几点注意事项:
**使用示例:**声明这一个注解,就相当于同时声明了@ComponentScan和@EnableDubbo
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ComponentScan
@DubboComponentScan
@interface SpringDubboScan {
@AliasFor(attribute = "basePackages", annotation = ComponentScan.class)
String[] springPackages() default {};
@AliasFor(attribute = "basePackages", annotation = DubboComponentScan.class)
String[] dubboPackages() default {};
}
@TableName(value = "sys_Log") //value作用:value指定数据库中的表名
public class SysLog {}
@TableId(type=IdType.AUTO) //声明主键自增长
private Long id;
@TableField(value = "email")//指定数据库表中字段名
@TableField(exist = "false")//数据库表中不存在的数据,在实体类中指定。
@TableField(select = "false")//查询时不返回该字段的值
@TableField (typeHandler = JsonObjectTypeHandler.class)
// typeHandler,类型转换器,就是将数据库中的类型与Java中的类型进行相互转换的处理器。
@TablieField(value = "create_time",fill = FieldFill.INSERT) //插入时自动填充
private LocalDateTime createTime;
@TablieField(value = "update_time",fill = FieldFill.INSERT_UPDATE) //更新时自动填充
private LocalDateTime updateTime;
mybatis下使用typeHandler
插入数据情景:
1、首先,我们需要编写一个typeHandler(以JSON转VARCHAR为例):
@MappedTypes(JSONObject.class)
@MappedJdbcTypes(JdbcType.LONGVARCHAR)
public class JsonObjectTypeHandler extends BaseTypeHandler<JSONObject> {
/**
* 插入数据时,将JSONObject转String
* @param ps
* @param i
* @param parameter
* @param jdbcType
* @throws SQLException
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, JSONObject.toJSONString(parameter));
}
}
注意,该typeHandler需要放在mapper文件夹下(即和mapper类放在一起,否则会找不到)
2、然后,在mapper.xml文件中,编写resultmap映射字段,并指定哪些字段需要使用typeHandler:
<!--字段映射,将数据库中String类型的json串映射为JSONObject,避免返回前段时两次序列化使得返回结果带反斜杠-->
<resultMap id="illnessMap" type="com.seven.springcloud.dto.IllnessDTO">
<result column="Weight" property="Weight" javaType="com.alibaba.fastjson.JSONObject" jdbcType="VARCHAR"
typeHandler="com.seven.springcloud.mapper.JsonObjectTypeHandler"/>
<result column="Add_date" property="Drug_Date"/>
</resultMap>
<!--查询所有病人的信息-->
<select id="selectUserIllness" resultMap="illnessMap">
select * from user_illness where Account=#{Account}
</select>
3、然后,实体类中,将字段类型设为JSONObject:
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY) //空值不返回
public class IllnessDTO implements Serializable {
private JSONObject Weight;
private String Drug_Date;
}
返回数据 情景:
@EqualsAndHashCode注解的作用就是自动实现model类的equals方法和hashcode方法。
@JsonProperty是jackson-databindjar包提供的注解,用于实体类的属性上, 功能是把属性名称转换为另一个名称(即,两个名称都指向同一个变量值)
注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响;
是Java Bean Validation框架中的一个注解,用于自定义约束注解,即自定义校验规则
可以将该注解标记为一个自定义约束注解。同时,需要指定一个实现了ConstraintValidator接口的验证器类,用于验证该注解所标记的字段或参数是否符合自定义的校验规则。
以下属性:
使用@Constraint注解,可以通过自定义注解的方式,为字段或参数添加自定义的校验规则,并实现校验逻辑。这样,在进行参数校验时,可以方便地通过注解的方式来调用自定义的校验规则。
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CustomValidator.class)
public @interface CustomConstraint {
String message() default "Invalid value";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class CustomValidator implements ConstraintValidator<CustomConstraint, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
// 自定义校验逻辑
return value.length() > 5;
}
}
public class CustomClass {
@CustomConstraint
private String field;
public void method(@CustomConstraint String param) {
// 方法体
}
}
public static void main(String[] args) throws NoSuchMethodException {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
CustomClass instance = new CustomClass();
// 针对字段进行校验
Set<ConstraintViolation<CustomClass>> violations = validator.validateProperty(instance, "field");
// 针对方法参数进行校验
Method method = CustomClass.class.getMethod("method", String.class);
Object[] args1 = new Object[] {"test"};
Set<ConstraintViolation<CustomClass>> violations1 = validator.forExecutables().validateParameters(instance, method, args);
}
上面的代码中,我们分别针对CustomValidator 类的field字段和method方法的param参数进行校验,并将校验结果存储在violations变量中。通过调用Validator的validateProperty和validateParameters方法,可以进行字段和方法参数的校验,校验结果为CustomValidator 对象的Set集合,其中包含了校验不通过的字段或方法参数的详细信息。
@component是spring中的一个注解,它的作用就是实现bean的注入
@Qualifier(“名称”):指定自动注入的id名称
是Lombok的一个注解,简化了我们对@Autowired书写
@AllArgsConstructor 生成一个包含所有字段的构造方法,
**注意:**如果使用了@Value注入,@Value注入会失效,原因时因为@Value注解是通过对象的set方法赋值的,构造方法的执行还在set方法之前,所以在构造方法中使用变量会变量为null。
@RequiredArgsConstructor会将类的每一个final字段或者non-null字段生成一个构造方法
总结:@AllArgsConstructor和@RequiredArgsConstructor都可以用来替代@Autowired写法,区别在于@RequiredArgsConstructor必须要有final修饰,如果有@Value注解,@RequiredArgsConstructor修饰可以成功注入,@AllArgsConstructor修饰会注入失败
@Override注解告诉你下面这个方法是从父类/接口继承过来的,需要你重写一次,这样就可以方便你阅读,也不怕会忘记。
省去实体类中大量的get()、 set()、 toString()等方法。
不能为 null,但可以为 empty,一般用在 Integer 类型的基本数据类型的非空校验上,而且被其标注的字段可以使用 @size、@Max、@Min 对字段数值进行大小的控制
不能为 null,且长度必须大于 0,一般用在集合类上或者数组上
只能作用在接收的 String 类型上,注意是只能,不能为 null,而且调用 trim() 后,长度必须大于 0即:必须有实际字符