cmd没有过滤java注释内容_java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题...

一、java自定义注解相关知识

注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关。使用得当特别方便。基于注解的xml文件配置方式也受到人们的推崇,其具有方便扩展,直观易懂,对现有的代码没有破坏性等等诸多优点。JAVA注解使用起来也比较简单。下面就简单讲一下使用自定义注解的方法。

(第一部分转自http://www.open-open.com/lib/view/open1353144218545.html)

1.定义注解

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inheritedpublic @interfaceDescription {

String value();

}

其中的@interface是一个关键字,在设计annotations的时候必须把一个类型定义为@interface,而不能用class或interface关键字。所有的注解类都隐式继承于 java.lang.annotation.Annotation,注解不允许显式继承于其他的接口。

一个注解可以拥有多个成员,成员声明和接口方法声明类似,这里,我们仅定义了一个成员,成员的声明有以下几点限制:

a)   成员以无入参无抛出异常的方式声明,如boolean value(String str)、boolean value() throws Exception等方式是非法的;

b)   可以通过default为成员指定一个默认值,如String level() default "LOW_LEVEL"、int high() default 2是合法的,当然也可以不指定默认值;

c)   成员类型是受限的,合法的类型包括原始类型及其封装类、String、Class、enums、注解类型,以及上述类型的数组类型。如ForumService value()、List foo()是非法的。

d)   如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=),如@Description("使用注解的实例")。注解类拥有多个成员时,如果仅对value成员进行赋值则也可不使用赋值号,如果同时对多个成员进行赋值,则必须使用赋值号,如@DeclareParents (value = "NaiveWaiter", defaultImpl = SmartSeller.class)。

e)   注解类可以没有成员,没有成员的注解称为标识注解,解释程序以标识注解存在与否进行相应的处理;

注解定义包含四个元注解,分别为@Target,@Retention,@Documented,@Inherited。各元注解的作用如下:

@Target

表示该注解用于什么地方,可能的 ElemenetType 参数包括:

Ø  ElemenetType.CONSTRUCTOR 构造器声明。

Ø  ElemenetType.FIELD 域声明(包括 enum 实例)。

Ø  ElemenetType.LOCAL_VARIABLE 局部变量声明。

Ø  ElemenetType.METHOD 方法声明。

Ø  ElemenetType.PACKAGE 包声明。

Ø  ElemenetType.PARAMETER 参数声明。

Ø  ElemenetType.TYPE 类,接口(包括注解类型)或enum声明。

@Retention

表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括:

Ø  RetentionPolicy.SOURCE 注解将被编译器丢弃。

Ø  RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃。

Ø  RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。

举一个例子,如@Override里面的Retention设为SOURCE,编译成功了就不要这一些检查的信息,相反,@Deprecated里面的Retention设为RUNTIME,表示除了在编译时会警告我们使用了哪个被 Deprecated的方法,在执行的时候也可以查出该方法是否被Deprecated。

@Documented

将此注解包含在 javadoc 中。(详细度娘)

@Inherited

允许子类继承父类中的注解。(详细度娘)

2.使用注解

@Description(value="zhujie")public classTestAnnotation {

}

使用注解的语法:@(=,=,...)

如果成员是数组类型,可以通过{}进行赋值,如boolean数组的成员可以设置为{true,false,true}。下面是几个注解标注的例子:

1)   多成员的注解

@AnnoExample(id= 2868724, synopsis = "Enable time-travel", engineer = "Mr. Peabody")

2)   一个成员的注解,成员名为value

可以省略成员名和赋值符号:@Copyright("Right Reserved")

@Copyright("2011 bookegou.com All Right Reserved")

3)   无成员的注解

@Override

4)   成员为字符串数组的注解

@SuppressWarnings(value={"unchecked","fallthrough"})

@SuppressWarnings(value={"unchecked","fallthrough"})

5)   成员为注解数组类型的注解

@Reviews({@Review(grade=Review.Grade.EXCELLENT,reviewer="df"),

@Review(grade=Review.Grade.UNSATISFACTORY,reviewer="eg",

comment="This method needs an @Override annotation")})

@Reviews({@Review(grade=Review.Grade.EXCELLENT,reviewer="df"),

@Review(grade=Review.Grade.UNSATISFACTORY,reviewer="eg",

comment="This method needs an @Override annotation")})

@Reviews注解拥有一个@Review注解数组类型的成员,@Review注解类型有三个成员,其中reviewer、comment都是String类型,但comment有默认值,grade是枚举类型的成员。

3.解析注解/获得注解属性

public classParseAnnotation {public static void main(String[] args) throwsException{final Class cls = Class.forName("com.annotation.TestAnnotation");final Method[] method =cls.getMethods();//判断是否有指定注解类型的注解

if(cls.isAnnotationPresent(Description.class)) {//根据注解类型返回指定类型的注解

Description des = (Description)cls.getAnnotation(Description.class);

System.out.println("注解描述:" +des.value());

}

}

}

输出结果如下:注解描述:zhujie

注解不能直接干扰程序代码的运行,无论增加或删除注解,代码都能够正常运行。Java语言解释器会忽略这些注解,而由第三方工具负责对注解进行处理。第三方工具可以利用代码中的注解间接控制程序代码的运行,它们通过Java反射机制读取注解的信息,并根据这些信息更改目标程序的逻辑,而这正是Spring AOP对@AspectJ提供支持所采取的方法。

二、SSH框架下,拦截器中无法获得java注解属性值的问题

上面的实例并不是在java web环境下运行,而我是在ssh环境下,想使用自定义注解。在拦截器中,我通过Class actionClass=invocation.getProxy().getAction().getClass()获得action的类,并通过以下代码获得目标action头上的注解属性信息。

if (actionClass.isAnnotationPresent(LogAnnotation.class)) {

LogAnnotation actionAnnotation= (LogAnnotation) actionClass.getAnnotation(LogAnnotation.class);

}

其中,自定义注解如下:

importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;importjava.lang.annotation.ElementType;

@Target( {ElementType.METHOD,ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)public @interfaceLogAnnotation {

String objectType();

}

目标action方法如下:

@LogAnnotation (objectType = "LogAction")public class LogAction extendsBaseAction {

@LogAnnotation (objectType= "LogView")publicString view() {}

}

可是,我在调试时actionClass.isAnnotationPresent(LogAnnotation.class)怎么也不能判断为真,获得actionAnnotation为null。

我将actionClass直接写为com.action.log.LogAction.class.isAnnotationPresent(LogAnnotation.class)是可以进入if语句,或得到actionAnnotation并获得由actionAnnotation.objectType()获得注解属性值。

断点调试时,actionClass为class com.action.log.LogAction$$EnhancerByCGLIB$$ea0373e6,可以发现后面多了一串东西$$EnhancerByCGLIB$$ea0373e6,刚人门,才疏学浅尚不知道这什么,可能是实现拦截器的cglib,具体原理我还没深究。查了很多资料,http://tieba.baidu.com/p/1782928180,http://stackoverflow.com/questions/15174599/classisannotationpresent-not-working。这个问答感觉和我这个遇到的有点点相似,但好像又不一样。找了很多资料,很久都不知道怎么解决。后来,我想,如果先把类转成string,再通过字符串截取把那个尾缀去掉,再转成类会不会就ok了?可能这个办法好像不官方,但也算一个方法了。

Class actionTempClass=invocation.getProxy().getAction().getClass();int i=actionTempClass.toString().indexOf("$$EnhancerByCGLIB");

String actionString=actionTempClass.toString().substring(6, i);

Class actionClass=Class.forName(actionString);//如果设置了注解则读取注解的内容,如果没有设置注解则记录登录的class名

if (actionClass.isAnnotationPresent(LogAnnotation.class)) {

LogAnnotation actionAnnotation= (LogAnnotation) actionClass.getAnnotation(LogAnnotation.class);

String objectTypeString=actionAnnotation.objectType();

}

经测试这个方案是可行的。同理action中的方法也可以通过此方法获得注解属性值。

Class actionTempClass=invocation.getProxy().getAction().getClass();int i=actionTempClass.toString().indexOf("$$EnhancerByCGLIB");

String actionString=actionTempClass.toString().substring(6, i);

Class actionClass=Class.forName(actionString);

String methodName=invocation.getProxy().getMethod();

Method method= actionClass.getMethod(methodName, null);//

//Method method = invocation.getAction().getClass().getMethod(methodName, null);//如果设置了注解则读取注解的内容,如果没有设置注解则记录登录的method名

if (method.isAnnotationPresent(LogAnnotation.class)) {

LogAnnotation methodAnnotation= (LogAnnotation) method.getAnnotation(LogAnnotation.class);

}

具体的导致原因还需要深究,敬请期待。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值