java自定义注解为空值_java自定义注解

用关键字@interface定义一个注解标记,使用@interface关键字实际上的意思就是该接口继承自java.lang.annotation.Annotation接口。

Java代码  

String isAop()default"false";

这句话代表的意思就是在Test注解中可以含有属性名为isAop,此属性的类型是字符串类型。客户端使用的时候可以根据需要自己指定相关的属性值。如果客户端不指定值,默认值是false

Java代码  

@Retention(RetentionPolicy.RUNTIME)

packageuse;

importannotation.Test;

importannotation.TestImpl.TestProcess;

@Test(isAop ="true")

publicclassUseTest {

publicstaticvoidmain(String[] args)throwsClassNotFoundException {

TestProcess.process("use.UseTest");

}

}

在客户端调用中在类UseTest上使用了@Test(isAop = "true")注解。仅仅定义了注解就像《三国杀》里,刘备是主公,他有“激将”的主公计,下了个命令:“蜀将何在?”,刘备的这句话太抽象了,蜀将相当于一个注解。在场的所有蜀将就像加了此注解的类,都会受到这句话的影响。具体替不替刘备出杀,~~~~个

人表现不同(得先看看自己的身份啊)反贼的表现是:“这个真没有”;忠臣的表现是,先看看手上有杀吗?有,出击吧!没有就说:“这个……真没有!”;内奸

的反应是:“唉,先保命还是装一装忠臣?比较纠结!”。这里的身份就好像是注解的属性的不同值。具体的处理就相当于针对注解的处理实现类。注解的具体实现

类就是处理注解的业务逻辑,它需要Java的反射机制来处理客户目标类的具体注解,我们就来看看这个注解处理实现类。

Java代码  

packageannotation.TestImpl;

importjava.lang.annotation.Annotation;

publicclassTestProcess {

publicstaticvoidprocess(String str)throwsClassNotFoundException {

Class clazz = Class.forName(str);

Annotation[] annotations = clazz.getAnnotations();

for(Annotation annotation : annotations) {

System.out.println(annotation);

}

}

}

以上的处理逻辑很简单,就是根据一个字符串类名找到类。获得类的所有注解,所有注解是一个对象数组。遍历注解数组,输出相关注解信息。运行以上的程序结果如下

Java代码  

@annotation.Test(isAop=true)

如果我们使用注解的客户端代码替换一下

Java代码  

@Test

publicclassUseTest {

……………………

}

对于注解的isAop并不特别指定。运行效果如下

Java代码  

@annotation.Test(isAop=false)

可以看到使用的是默认值false。如果注解中Annotation并没有指定默认值,而在客户端使用中也没指定值,那么不会通过编译。

@Retention(RetentionPolicy.XXXXXX)上面说到了是保留注解的有效期。

Java代码  

//会将注解保留到编译后的class中,加载类的时候不生效

@Retention(RetentionPolicy.CLASS)

//仅仅在代码保留,编译后的class不会保留

@Retention(RetentionPolicy.SOURCE)

//在编译后的class会有,通过反射也会获得注解信息

@Retention(RetentionPolicy.RUNTIME)

比如Override注解的源码

Java代码  

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.SOURCE)

public@interfaceOverride {

}

因为复写在使用者使用的时候就可以看出来,所以没必要保留到运行期。

比如SuppressWarnings注解的源码

Java代码  

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})

@Retention(RetentionPolicy.SOURCE)

public@interfaceSuppressWarnings {

String[] value();

}

以上的不提示警告的注解也是在编译一个类前检查即可。

以上还使用了@Target注解,它代表着注解的修饰范围,类型是java.lang.annotation.ElementType枚举类型。

Java代码  

publicenumElementType {

TYPE,//可以修饰类、接口、枚举、注解

FIELD,//可以修饰成员变量

METHOD,//可以修饰方法

PARAMETER,//可以修饰参数

CONSTRUCTOR,//可以修饰构造方法

LOCAL_VARIABLE,//可以修饰局部变量

ANNOTATION_TYPE,// 可以修饰Annotation

PACKAGE//可以修饰包

}

看Deprecated源码

Java代码  

@Documented

@Retention(RetentionPolicy.RUNTIME)

public@interfaceDeprecated {

}

Deprecated代表已过时的意思,这是一个保持到运行期的注解,在运行期可以通过反射获取此注解。文档中的内容会因为此注解的信息内容不同而不同。

还有一个注解就是Inherited,如果使用了该标记,那么使用该注解的子类也会继承该注解的特性。

3.

实例

很多人有疑问,你说这些有什么用?对于开发有什么促进吗?EJB注解、JPA注解我们会使用完成业务不就得了。下面再来看一个程式例子

注解Pojo

Java代码  

packageannotation;

importjava.lang.annotation.ElementType;

importjava.lang.annotation.Retention;

importjava.lang.annotation.RetentionPolicy;

importjava.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public@interfacePojo {

String table();

}

注解Colum

Java代码  

packageannotation;

importjava.lang.annotation.ElementType;

importjava.lang.annotation.Retention;

importjava.lang.annotation.RetentionPolicy;

importjava.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public@interfaceColum {

String columName();

booleanisNULL()defaulttrue;

String Type() default"";

}

处理注解的逻辑实现类

Java代码  

packageannotation.TestImpl;

importjava.lang.annotation.Annotation;

importjava.lang.reflect.Field;

importannotation.Colum;

importannotation.Pojo;

publicclassMyJPAProcess {

publicstaticvoidprocess(Object object)throwsClassNotFoundException {

// 所有注解

Annotation[] annotationsClass = object.getClass().getAnnotations();

Field[] fields = object.getClass().getDeclaredFields();

// 遍历注解元素

for(Annotation annotation : annotationsClass) {

if(annotationinstanceofPojo) {

System.out.println("--------处理POJO实体--------");

Pojo pojo = (Pojo) annotation;

System.out.println("存储表名:"+ pojo.table());

}

}

for(Field field : fields) {

//field.setAccessible(true);

Annotation[] annotationsMethos = field.getAnnotations();

// 遍历注解元素

for(Annotation annotation : annotationsMethos) {

if(annotationinstanceofColum) {

System.out.println("--------处理Colum字段--------");

Colum colum = (Colum) annotation;

System.out.println("字段名:"+ colum.columName());

System.out.println("字段类型:"+ colum.Type());

System.out.println("是否能为空:"+ colum.isNULL());

}

}

}

}

}

以上是定义了简单的2个注解Pojo和Colum。之后为这2个注解提供了逻辑处理。下面我们来看看客户端是怎么使用的吧。

一般的实体类

Java代码  

packageuse;

importannotation.Colum;

importannotation.Pojo;

@Pojo(table ="person")

publicclassPersionPOJO {

publicPersionPOJO() {

super();

}

@Colum(columName ="id", isNULL =false, Type ="varchar")

privateString id;

@Colum(columName ="name", isNULL =false, Type ="varchar")

privateString name;

@Colum(columName ="age", isNULL =true, Type ="int")

privateintage;

//省略set/get

}

这是一个普通的实体对象+自定义的注解。针对于这个POJO我们再定义一个DAO类操作这个POJO类。

Java代码  

packageuse;

importannotation.TestImpl.MyJPAProcess;

publicclassPersionDAO {

publicvoidsave(PersionPOJO persionPOJO)throwsClassNotFoundException {

MyJPAProcess.process(persionPOJO);

}

publicstaticvoidmain(String[] args)throwsClassNotFoundException {

PersionDAO persionDAO = newPersionDAO();

PersionPOJO persionPOJO = newPersionPOJO();

persionDAO.save(persionPOJO);

}

}

上面程序就定义了一个保存方法,测试一下,调用这个save方法。控制台输出如下信息。

Java代码  

--------处理POJO实体--------

存储表名:person

--------处理Colum字段--------

字段名:id

字段类型:varchar

是否能为空:false

--------处理Colum字段--------

字段名:name

字段类型:varchar

是否能为空:false

--------处理Colum字段--------

字段名:age

字段类型:int

是否能为空:true

DAO中调用了注解逻辑实现类的方法。这个时候我们稍微修改一下注解逻辑实现类的方法,配合一个ORM中间件,就可以将数据保存到数据库了。

4.

总结

其实自定义注解一般是公司或者团队觉得一些原有的配置比较麻烦,加上注解是为了减少配置。还有一个目的:自己开发框架,让自己的团队更敏捷、更快速的相应纷繁错杂的客户需求。其实还有一个目的:就是制定规范,JPA是规范、EJB是规范……至于底层对于这些注解规范的实现则因不同的容器决定的。所谓容器就是JBoss或者Weblogic这种JavaEE容器的自己的jar包,像Java

SDK也是提出了相应的规范,不同的组织对这个规范的实现也是仁者见仁智者见智,像上面提出的JDK内的注解就是提出了规范,我自己sun有一套实现机制,其他的组织用我sun的JDK实现不爽也可以自行实现这套注解机制。这样通过反射机制获取本应该在配置文件中配置的一些信息。减少了冗余的配置文件。至于效率嘛~~~有人说反射机制比解析配置慢、有人说配置文件要是过长会比反射慢很多。这个笔者觉得仁者见智者见智,没有绝对的答案,到底使用哪个?还是得因环境而异。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值