Java自定义属性转载
原创前言
随着springboot的受欢迎程度,以前是基于XML的spring配置越来越少,JavaConfig表格的使用越来越多,相似:
复制代码
@Configuration
public class AppConfig {
@Bean(name="helloBean")
public HelloWorld helloWorld() {
return new HelloWorldImpl();
}
}
可以看出,更多的是基于注释。(Annotation)已实现,包括springboot的入口类**Application。
复制代码
@Configuration
@ComponentScan("com.alibaba.trade")
@EnableAutoConfiguration//(exclude = {PageHelperAutoConfiguration.class})
@ServletComponentScan
@EnableTransactionManagement
@EnableDiscoveryClient
@EnableWebMvc
@MapperScan("com.alibaba.trade.shared.mapper")
public class TradeApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(TradeApplication.class, args);
}
}
Java批注不仅允许我们减少XML文件,这便于维护,也使我们的代码更简洁。那么,我们如何在项目中读取批注并创建自己的批注呢?
注解说明
Java注解又称Java标注,是Java语言5.0该版本开始支持用于添加源代码的特殊语法元数据。它为我们提供了一种将信息添加到代码中的正式方法,以便我们可以在以后非常方便地使用数据。
Java可以标记该语言中的类、方法、变量、参数和包。和Javadoc不同,Java批注可以通过反射获取批注内容。当编译器生成类文件时,注释可以嵌入到字节码中。Java虚拟机可以在运行时保留注释内容并获取注释内容。
内置注解
Java 定义一组共享的注释 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
1作用于代码的注释是
@Override
- 检查该方法是否为重写方法。如果找到它的父类,或者如果引用的接口中没有这样的方法,则将报告编译错误。@Deprecated
- 标记过时的方法。如果使用此方法,将报告编译警告。@SuppressWarnings
- 指示编译器忽略批注中声明的警告。
2,在其他注释中的角色(或者说 元注解 )是:
@Retention
- 确定此批注是如何保存的,是仅保存在代码中还是合并到代码中class文件,或者可以在运行时由反射访问。@Documented
- 标记这些备注是否包含在用户文档中。@Target
- 标记哪种批注应为 Java 成员。@Inherited
- 标记此批注从哪个批注类继承(默认 该批注不是从任何子类继承的。)
3、从 Java 7 首先,请添加其他 3 个注解:
@SafeVarargs
- Java 7 开始支持,忽略使用参数作为泛型变量的方法或构造函数调用生成的任何警告。@FunctionalInterface
- Java 8 开始支持,识别匿名函数或函数接口。@Repeatable
- Java 8 开始支持时,可以在同一声明上多次使用标识注解。
元注解
1、 @Retention
@Retention
annotation指定标记注释的存储方式:
- RetentionPolicy.SOURCE - 标记的注释仅保留在源代码级别,并被编译器忽略。
- RetentionPolicy.CLASS - 标记的评论编译器在编译时保留。Java虚拟机(JVM)将被忽略。
- RetentionPolicy.RUNTIME - 标记的评论JVM保留,以便运行时环境可以使用它。
2、 @Documented
@Documented
注释指示无论何时使用指定的注释,都应使用该注释Javadoc用于记录这些元素的工具。(默认情况下,注释不包括在JavadocIn。)有关详细信息,请参阅 Javadoc工具页。
3、 @Target
@Target
备注标记另一个备注以限制可以应用的备注数量。Java元素类型。目标批注将以下元素类型之一指定为其值
- ElementType.TYPE 可以应用于类的任何元素。
- ElementType.FIELD 可以应用于字段或属性。
- ElementType.METHOD 可应用于方法级批注。
- ElementType.PARAMETER 可应用于该方法的参数。
- ElementType.CONSTRUCTOR 可以应用于构造函数。
- ElementType.LOCAL_VARIABLE 可以应用于局部变量。
- ElementType.ANNOTATION_TYPE 可应用于注释类型。
- ElementType.PACKAGE 可应用于包声明。
- ElementType.TYPE_PARAMETER
- ElementType.TYPE_USE
4、 @Inherited
@Inherited
注释指示注释类型可以从超类继承。当用户查询评论类型并且类没有这种类型的评论时,查询类的超类以获得评论类型(不是默认的)。此注释仅适用于类声明。
5、 @Repeatable
Repeatable Java SE 8引入, @Repeatable
注释指示标记的注释可以多次应用于同一声明或类型。(也就是说,它可以在相同的类、方法、属性等上重复使用。)。
自定义注释
Java中自定义注释和创建一个接口相似,自定义注释的格式是以@interface有记号的。
复制代码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SPI {
/**
* default extension name
*/
String value() default "";
}
我们知道java.lang.annotation包裹里有一件。Annotation的接口,它是所有注解类型扩展的公共接口。那我们是否可以直接通过实现该接口来实现自定义注释呢?
复制代码
import java.lang.annotation.Annotation;
public class MyAnnotation implements Annotation {
@Override
public Class extends Annotation> annotationType() {
return null;
}
}
发现Annotation只有一个接口annotationType方法,通过源代码注释我们可以发现答案是否定的。
中文译文如下:Annotaion由所有批注类型继承,但请注意,手动扩展继承此接口的接口并不定义批注类型。还要注意的是,该接口本身并没有定义注释类型。
使用场景
自定义注释的使用场景很多,我们在造轮子写框架的过程经常会使用到,例如我最近就遇到了一个业务场景:像一些编辑业务信息的接口,产品要求信息编辑后的新旧值对比,对比的业务功能,我们的实现方式是拿到前端填写的Form表单(新值)并对数据库进行查询。Dto(旧值)通过反射技术获得相同的属性字段名,并通过比较属性值获得新旧的值。在获得值之后,我们还知道该字段的Dto但如何将新旧值域的中文名返回到前端呢?例如:
复制代码
public class Stedent {
private String name;
private int age;
private String sex;
//省略setter,getter
}
经过比较,我们的结果是 name : "xiaoming "-> "daming",age : 24 -> 26。但我们不能直接name和age返回到前端,他们需要的格式是:名称: "xiaoming "-> "daming",年龄 : 24 -> 26。这是您可以考虑自定义注释的地方。 @FieldName
,
复制代码
@Deprecated
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldName {
String value() default "";
}
然后将注释添加到属性字段的上方。
复制代码
public class Student {
@FieldName(value = "姓名")
private String name;
@FieldName(value = "年龄")
private int age;
@FieldName(value = "性别")
private String sex;
//省略setter,getter
}
然后,可以通过反射获得该字段的中文名称。
复制代码
// 如果 oldField 属性值与 newField 属性值的内容不相同。
if (!isEmpty(newValue)) {
Map map = new HashMap<>();
String newFieldName = newField.getName();
//在这里获取注释的信息。
if (newField.isAnnotationPresent(FieldName.class)) {
FieldName fieldNameAnno = newField.getAnnotation(FieldName.class);
newFieldName = fieldNameAnno.name();
}
map.put(FIELD_NAME, newFieldName);
map.put(OLD_VALUE, oldValue);
map.put(NEW_VALUE, newValue);
list.add(map);
}
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除