• 2010年Java高新技术A(3)内省 JavaBean 注解


    1 什么是javaBean

     JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要是用于访问私有字段,且方法名符合某种命名规则.

    2 javaBean有什么作用

           如果要在两个模块之间传递多个信息,可以讲这些信息封装到一个javaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object 建成VO)。这些信息在类中用私有字段来存数,想要获取这些信息可以通过一定的方法来获取。

    3 如何获取JavaBean中的信息

           JavaBean中的属性是根据其中的getter和setter方法确定的,并不是根据其中的成员变量,如果方法名为setId,中文意思即为设置 ID,至于把它存在哪个变量上,无所谓都是表示设置ID 同样如果方法名字为getID 中文意思即为获取ID至于从哪个变量上去,无所谓都是表示取ID,一般按照如下规则命名 去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的

    如setId()àid; isLast()àlast;  setCPU—>CPU;      getupsàUPS;

    总之一个类被当做javabean使用时,javaBean的属性石根据方法名推断出来的,它根本看不到Java类内部的成员变量

    4     JavaBean的好处

           在JavaEE开发中,经常要使用JavaBean,很多环境就要求按JavaBean方式进行操作,主流。

           JDK中提供了对JavaBean进行操作的一些API,这些API就称为内省,如果要你自己去通过getX 方法来访问私有的X是由一定难度的,用内省这套API操作JavaBean比普通类的方式要方便。

     5示例对JavaBean的操作

     

    1. package cn.itheima.fanshe;  
    2.   
    3. import java.beans.PropertyDescriptor;  
    4. import java.lang.reflect.Method;  
    5.   
    6. public class beantest {  
    7.   
    8.       
    9.     public static void main(String[] args) throws Exception{  
    10.         //通过bean方式获取对象 rd1的name值  
    11.         RoleDemo rd1 = new RoleDemo("张三","type1");  
    12.         //定义一个要获取的属性名 这个是name  
    13.         String propertyName = "name";  
    14.         //获取属性 参数 指定要获取的属性,和指定的类  
    15.         PropertyDescriptor pd = new PropertyDescriptor(propertyName,rd1.getClass());  
    16.         //得到属性了 进一步就可以得到属性的get set方法 如下即可得到了X属性的读方法  
    17.         Method methodgname = pd.getReadMethod();  
    18.         //有了这个属性的读方法我们就可以用这个方法在rd1方法上调用。  
    19.         Object retval   = methodgname.invoke(rd1);  
    20.         System.out.println(retval);  
    21.         //输出 调用了带两个属性的构造器 张三  
    22.           
    23.         Method methodsname = pd.getWriteMethod();  
    24.         //有了这个属性的读方法我们就可以用这个方法在rd1方法上调用。  
    25.         Object retval1   = methodsname.invoke(rd1,"李四");  
    26.         System.out.println(rd1.getName());  
    27.         //输出 李四  
    28.           
    29.     }  
    30.   
    31. }  

    可以到上面获取属性值的时候有代码复用,那么可以抽取出来构成一个方法,用的时候调用即可

    1. package cn.itheima.fanshe;  
    2.   
    3. import java.beans.IntrospectionException;  
    4. import java.beans.PropertyDescriptor;  
    5. import java.lang.reflect.InvocationTargetException;  
    6. import java.lang.reflect.Method;  
    7.   
    8. public class beantest {  
    9.   
    10.       
    11.     public static void main(String[] args) throws Exception{  
    12.         //通过bean方式获取对象 rd1的name值  
    13.         RoleDemo rd1 = new RoleDemo("张三","type1");  
    14.         //定义一个要获取的属性名 这个是name  
    15.         String propertyName = "name";  
    16.           
    17.         Object retval = getProperty(rd1, propertyName);  
    18.         System.out.println(retval);  
    19.         Object newVal = "李四";  
    20.         //输出 调用了带两个属性的构造器 张三  
    21.   
    22.         getProperts(rd1, propertyName, newVal);  
    23.         System.out.println(rd1.getName());  
    24.         //输出 李四  
    25.           
    26.     }  
    27.     private static void getProperts(Object rd1, String propertyName,  
    28.             Object newVal) throws IntrospectionException,  
    29.             IllegalAccessException, InvocationTargetException {  
    30.         PropertyDescriptor pd = new PropertyDescriptor(propertyName,rd1.getClass());  
    31.         Method methodsname = pd.getWriteMethod();  
    32.         Object retval1   = methodsname.invoke(rd1,newVal);  
    33.     }  
    34. //重构的方法  
    35.     private static Object getProperty(Object rd1, String propertyName)  
    36.             throws IntrospectionException, IllegalAccessException,  
    37.             InvocationTargetException {  
    38.         PropertyDescriptor pd = new PropertyDescriptor(propertyName,rd1.getClass());  
    39.         Method methodgname = pd.getReadMethod();  
    40.         Object retval   = methodgname.invoke(rd1);  
    41.         return retval;  
    42.     }  
    43.   
    44. }  

    对JavaBean的复杂内省操作:在IntroSpector类中有getBeanInfo(Class cls)的方法。

    获取Class对象的Bean信息,返回的是BeanInfo类型。

    BeanInfo类中有getPropertyDescriptors()的方法,可获取所有的BeanInfo的属性信息,返回一个PropertyDescriptor[]。

    在通过遍历的形式,找出与自己想要的那个属性信息。

    如:改写get方法:

    1. ...  
    2. BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());    
    3.         PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();    
    4.         Object value = null;    
    5.         for(PropertyDescriptor pd : pds){    
    6.             if(pd.getName().equals(propertyName)){    
    7.                 Method methodGetX = pd.getReadMethod();    
    8.                 value = methodGetX.invoke(pt1);    
    9.                 break;    
    10.             }    
    11.         }    
    12. …    

    6    Beanutils工具包

           为了便于操作JavaBean,前辈们就编写了BeanUtils包,里面封装了很多对JavaBean的操作,我们在用的时候可以直接拿过来用。

    好处是什么呢有如下三个好处

           一提供的set或get方法中,传入的是字符串,返回的还是字符串,因为在浏览器中,用户输入到文本框的都是以字符串形式发送至服务器上的,所以操作的都是字符串。也就是说,这个工具包的内部有自动将证书转换为字符串的操作

           一是支持属性的级联操作,即支持属性链,如果可以设置,人的脑袋上的眼睛的眼珠的颜色。这种级联属性的属性链如果用自己反射,那就很困难了通过这个工具包就可以轻松调用。

           一是 可以和Map集合进行相互转换,可以讲属性信息通过键值对的形式作为Map集合存储(通过 staticJava.util.Mapdecribe(java.lang.Objectbean)的方法)也可以讲Map集合转换为JavaBean 中的属性信息,(通过static void populate(java.lang.object bean,java.util.map properties)的方法)。

    上面我们介绍了通过bean方式获取对象 rd1的name值的方法,下面我们可以利用BeanUtils包简化操作

    1. //通过bean方式获取对象 rd1的name值  
    2.         RoleDemo rd1 = new RoleDemo("张三","type1");  
    3.         //定义一个要获取的属性名 这个是name  
    4.         String propertyName = "name";  
    5. System.out.println(BeanUtils.getProperty(rd1, propertyName));  
    6.         BeanUtils.setProperty(rd1, propertyName, "李四");  
    7.         System.out.println(rd1.getName());  
    8. 输出张三 李四 显然简化了操作  

    注解

    java提供的几个基本注解

    1、  @suppressWarning(“deprecation”)à压制警告

           suppressWaring是告知编译器或开发工具等提示指定的编译器警告

           deprecation 是告知具体的信息即方法已过时

    2、  @Deprecatedà提示成员已经过时,不再推荐使用。

           源代码标记@Deprecated是在JDK1.5中作为内置的annotatin引入的,用于表明类、方法、字段已经不再推荐使用,并且在以后的JDK 版本中,可能将其删除,在编译器在默认情况下检测到此标记时,会提示警告信息:假如之前的某个类升级了,其中的某个方法已经过时了,不能够将过时的方法删 除,因为可能会影响到调用此类的这个方法的某些程序,这是就可以通过在方法上加这个注解。

    3、@Overrideà提示覆盖(父类方法)

    加上此注解,可对自己类中的方法判断是否是要覆盖的父类的方法,典型的例子即在集合中覆盖equals(Object obj)方法,其中的参数类型必须是Object,才能被覆盖,若不是,加上此注解就会提示警告。

    总结

           注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后javac编译器,开发工具盒其他程序可以用反射来了 解你的类及各种元素上有无何种标记,看你有什么标记就去干相应的事,标记可以加在包,类,字段,方法,方法的参数上以及局部变量上

    4、  自定义注解

           自定义注解和接口差不都 ,只是在interface前面加一个@

    public @interface Myannotation {} 这个代码是一个最简单的注解,这个注解没有属性,也可以理解为是一个标记注解。就像Serlializable接口一样是一个标记接口,里面未定义方法。 也可以再里面加上方法public @interface MyAnnotation{String value() }

           使用子低昂一注解

           @MyAnnotation(“abc”)

           publicvoid myMethod(){}

    这里的abc传给了Value 有个规定就是如果没有属性名称的值,而这个注解有有Value属性,就将这个值赋给Value属性,如果没有,就出现编译错误。

     

    在使用的时候出了可以省略属性值,还可以使用默认值

    1. public @interface MyAnnotation  
    2. {  
    3.     public String MyMethod() default “abc”;  
    4. }  
    5. //使用默认值  
    6. @MyAnnotation  
    7. public void MyMethod(){}  

    5、  对注解进行注解

           为注解提供的注解叫做 元注解  这种注解主要是 Target Retention Documented 和 Inherited

    1)  Target

    target表示目标,这个注解在用的时候是与某一些目标相关的。看如下示例

    1.  @Target({ElementType.METHOD})  
    2. @interface MyAnnotation{}  
    3. @MyAnnotation //放在类上面是错误的  
    4. public class Class1  
    5. {  
    6.     @MyAnnotation  
    7.     public void myMethod1(){}  
    8. }  

    上面这段代码定义了一个注解MyAnnotation和一个类Class1,使用MyAnnotation分别对Class1和myMethod1进行注解,编译这段代码是无法通过的,因为@Target({ElementType.METHOD})

    指定了使用注解的目标是一个方法而不是其他任何语句元素。。由此看见,target所指定的目标就是java中的语句元素,比如类,接口,方法等。 比如只可以对方法和构造函数进行注解可以写成

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

    @interfaceMyAnnotation{}

    2)  Retention

    注解只有在被保存到class文件中才可以被读出来,Retention就是为设置注解是否保存在class文件中而存在的。详细用法如下

    //不将注解保存在class文件中,类似 // 一样在编译时被过滤掉

    @Retention(RetentionPolicy.SOURCE)

    @interface MyAnnotation1{}

    //只将注解保存在class文件中,在运用反射读取注解时忽略掉这些注解。

    @Retention(RetentionPolicy.CLASS)

    @interface MyAnnotation2{}

    //将注解保存在class文件中,通过反射也可以读出注解

    @Retention(RetentionPolicy.RUNTIME)

    @interface MyAnnotation3{}

    3)  Documented

    这个注解跟文档有关,在默认的情况下使用javadoc自动生成文档时,直接将被忽略掉,如果想在文档中包含注解那必须使用Documented为文档注释,例如

    1. @interface MyAnnotation{ }  
    2.     @MyAnnotation  
    3.     class Class1  
    4.     {      
    5.      public void myMethod() { }  
    6.     }  

    在使用的javadoc为这段代码生成文档时并不将@MyAnnotation包含进去。生成的文档对Class1的描述为 class Class1 extends java.lang.Object

    如果这样定义MyAnnotation将会出现另一个结果。

    @Documented

    @interface MyAnnotation{}

    生成文档为

    @MyAnnotation

    class Class1 extendsjava.lang.Object

     

    4)  Inherited

     这个是关于继承方面的元注解,不向protected和public成员都将被子类继承一样,在默认的情况下,父类的注解并不会被子类继承,如果要继承,就必须加上Inherited

    1. @Inherited  
    2. @interface MyAnnotation { }  
    3.   
    4. @MyAnnotation  
    5. public class ParentClass {}  
    6.   
    7. public class ChildClass extends ParentClass { }  
    8. 在以上代码中ChildClass和ParentClass一样都已被MyAnnotation注解了。  

    6、  通过反射查看注解

           在JDK1.5以后可以通过反射来获取注解了。之前的版本是不可以的。

           想要得到某一个类或接口的租借信息,可以使用下面代码

           Annotationannotation = AnnotationTest.calss.getAnnotation(MyAnnotation.class);

           想要得到全部的注解信息可以用如下方式

           //包括继承的所有注解

           Annotation[]annotations =AnnotationTest.class.getAnnotations();

    //不包括继承的所有注解

    Annotation[] anntations     = AnnotationTest.class.getDeclaredAnnotations()

  • 相关阅读:
    「CH6801」棋盘覆盖
    「POJ3613」Cow Relays
    「Luogu4556」Vani有约会-雨天的尾巴
    The Proof of Fibonacci GCD
    Ubuntu flatabulous 主题
    CSP-S 2019 复赛游记
    「Luogu1402」酒店之王
    HDU/5499/模拟
    cfedu/A/求和
    HDU<1372>/bfs
  • 原文地址:https://www.cnblogs.com/guwenren/p/3010951.html
Copyright © 2020-2023  润新知