框架,JavaBeans与内省(Introspector)
来源:互联网 发布:苹果mac怎么下载 编辑:程序博客网 时间:2024/06/06 14:17
本文转自:http://www.cnblogs.com/yiqiu2324/p/3204322.html?utm_source=tuicool
1.Java框架(frame)
/*通俗例子: 我做房子(框架)卖给用户住,由用户自己安装门窗和空调(用户自定义类/用户自定义其它信息) 用户需要使用我的房子(框架),把符合框架中结构的门窗插入进我提供的框架中.框架与工具类区别: 框架调用用户提供的类 工具类被用户的类调用示例: 利用反射运行指定的某个类中的main方法, 通过arg[0]来接收要运行的类名,也就是说 我已写好这个功能,而你要运行的类还不存在 我这个功能可以提前编译,你只需在运行时提供给我要运行的类即可.框架要解决的核心问题: 我若干年前写的程序调用你若干年后写的程序->反射机制为什么要用框架? 框架相当于半成品->也就是说提高开发效率*/模拟框架:利用反射机制读取配置文件
public class FrameMN { public static String loadProp()throws IOException{ Properties property=new Properties(); BufferedInputStream bis=null; InputStream is=null; try{ /* bis=new BufferedInputStream (new FileInputStream("config.properties"));//这里的根目录为工程名称(JavaEnhance) //"config.properties"相当于".\\config.properties"*/ System.out.println(System.getProperty("java.class.path"));//classpath路径 /* bis=new BufferedInputStream(FrameMN.class.getClassLoader().getResourceAsStream ("com/itheima/day2/config.properties"));//将会在classpath+指定的路径(com/itheima/day2/config.properties) //下查找,com前面不能有/->将不再是相对路径 */ bis=new BufferedInputStream(FrameMN.class.getResourceAsStream("/com/itheima/day2/config.properties")); property.load(bis); return property.getProperty("className"); } finally{ if(bis!=null) bis.close(); } } public static void main(String[] args)throws Exception{ String className=loadProp(); Collection collections=(Collection)Class.forName(className).newInstance(); collections.add("3"); collections.add(2); System.out.println(collections);//[3, 2] System.out.println(System.getProperty("user.dir")); }}目录结构:
注意几点:
/*config.properties 该如何配置其位置?1.相对路径 其实就是System.getProperty("user.dir"); 相对路径随时有可能在变,但是可以通过 System.getProperty("user.dir")来获取当前程序执行所在的相对路径. 但是如果这个文件不再当前路径下->找不到引发IO异常2.绝对路径 从盘符开始路径:d:\abc\1.txt 不建议使用这样做缺点:用户没有d:盘符呢?解决办法: 例如:把某个软件安装到某个目录->通过方法获取到其安装路径->在与内部的配置文件拼接形成绝对路径一个错误: Frame.class.getClass()*//* 1.eclipse在你src下新建.java文件后它会自动编译成.class文件放在bin目录下 2.当在src下创建文件->eclipse将该文件拷贝一份到bin目录下 在src某个包下创建文件->eclipse将该文件拷贝一份到bin目录的相同包下*//* 注意: Class类: public InputStream getResourceAsStream(String name) 此方法委托此对象的类加载器。如果此对象通过引导类加载器加载, 则此方法将委托给 ClassLoader.getSystemResourceAsStream(java.lang.String)。 在委托前,使用下面的算法从给定的资源名构造一个绝对资源名: 如果 name 以 '/' 开始 ('\u002f'),则绝对资源名是 '/' 后面的 name 的一部分。 否则,绝对名具有以下形式: modified_package_name/name其中 modified_package_name 是此对象的包名,该名用 '/' 取代了 '.' ('\u002e')。 例如:<截图> 配置文件和运行类在同一个包下: 1. getResourceAsStream("/com/itheima/day2/config.properties") 相当于调用ClassLoader.getResoureceAsStream("com/itheima/day2/config.properties") 2.getResourceAsStream("config.properties") ->com/itheima/day2/config.properties(此字节码对象的包名+指定的路径)-> ClassLoader.getResoureceAsStream("com/itheima/day2/config.properties") 配置文件和运行类不在同一包下: 1.在com.itheima.day2.resources下 依然用Class的getResourceAsStream("resource/com/itheima/day2/config.properties"); 2.如果在com.ithmeima.day1下 "/com/itheima/day1/config.properties" */
2.JavaBean与Introspector
/* JavaBean与内省(Introspector): 1.JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法 主要用于访问私有字段,且方法名符合某种命名规则.2.如果在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例通常称之为值对象(Value Object).这些信息在类中用私有字段来存储,如果读取货设置这些字段的值则需要通过一些相应的方法来访问,这些方法该如何命名? JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量.如果方法名为setId,意为设置id,至于你存到哪个变量上,用管吗?getId意为获取id,至于从哪个变量上得到的,用管吗?去掉set前缀后,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小写. setId属性名->id isLast属性名->last setCPU属性名->CPU 总而言之:一个类被当做JavaBean使用时,JavaBean的属性是根据方法名推断出来的 它根本看不到java类内部的成员变量一个符合JavaBean特点的类可以被当做普通类一样进行使用,但把它当做JavaBean用肯定需要带来一些额外的好处好处: 1.在JavaEE开发中,经常使用JavaBean.很多环境要求按JavaBean方式进行操作 2.JDK提供了对JavaBean进行操作的一些API,这套API就称为内省.*///eclipse 4.3下自动生成getter和setter方法//JavaBean的属性是由getter或setter方法决定
//只要含有其中的一个方法就是JavaBean的属性
//User类继承Object的方法getClass,因此还有一个属性为classclass User{ private String userName;//字段 private String uName;//字段 private String CPU; private String controlProcessUnited; private int x; public int getX() { return x; } public void setX(int x) { this.x = x; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getuName() { return uName; } public void setuName(String uName) { this.uName = uName; } public String getCPU() { return CPU; } public void setCPU(String cPU) { CPU = cPU; } public String getControlProcessUnited() { return controlProcessUnited; } public void setControlProcessUnited(String controlProcessUnited) { this.controlProcessUnited = controlProcessUnited; } }对JavaBean内省操作:
用一个测试类:Car
package com.itheima.day2;import java.util.Date;public class Car { private String color; private int number;//轮胎个数 private Date birthday=new Date();//为了测试 设置级联属性 public Car(String color, int number) { super(); this.color = color; this.number = number; } public String getColor(){ return color; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; }public void setColor(String color) { this.color = color; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } }
package com.itheima.day2;import java.lang.reflect.Method;import java.beans.BeanInfo;import java.beans.Introspector;import java.beans.PropertyDescriptor;public class IntrospectorDemo { public static void main(String[] args)throws Exception{ // TODO 自动生成的方法存根 //方式一:使用反射操作JavaBean //获取颜色->color->color有一个单词第二个字母小写->推断出方法名getColor Car car=new Car("红色",4); Method method=car.getClass().getMethod("getColor"); Object retVal=method.invoke(car); System.out.println(retVal);//"红色" //方式二:使用内省操作JavaBean->不用再推断方法名 PropertyDescriptor pd=new PropertyDescriptor("color",car.getClass());//第一个参数属性名,第二个参数把哪一个类当成JavaBean类 method=pd.getReadMethod();//将获取到的getColor方法封装成Method对象 retVal=method.invoke(car); System.out.println(retVal);//"红色" method=pd.getWriteMethod();//将获取到的setColor方法封装成Method对象 method.invoke(car,"黑色"); System.out.println(car.getColor());//验证是否改掉//"黑色" //测试封装后的方法 System.out.println(getProperty("number",car));//4 setProperty("number",car,10); System.out.println(car.getNumber());//10 } //对上面的操作步骤进行封装提高复用性 public static Object getProperty(String property,Object obj) throws Exception{//获取指定对象的属性值 PropertyDescriptor pd=new PropertyDescriptor(property,obj.getClass()); Method method=pd.getReadMethod(); return method.invoke(obj); /*//方法二: BeanInfo bi=Introspector.getBeanInfo(obj.getClass());//在 Java Bean 上进行内省,了解其所有属性、公开的方法和事件,描述目标 bean 的 BeanInfo 对象。 PropertyDescriptor[] pdArrs=bi.getPropertyDescriptors();//获取到该JavaBean中所有属性信息,BeanInfo没有获取单个属性的方法 for(PropertyDescriptor pdArr : pdArrs) if(pdArr.getName().equals(property)){//获取到属性描述的属性名称(getName),遍历 Method method=pdArr.getReadMethod(); return method.invoke(obj); } return null;*/ } public static void setProperty(String Property,Object obj,Object value)throws Exception{ PropertyDescriptor pd=new PropertyDescriptor(Property,obj.getClass()); Method method=pd.getWriteMethod(); method.invoke(obj,value); } }
使用开源工具BeanUtils来操作JavaBean:
/* 使用开源BeanUtils来更方便操作JavaBean 1.从http://commons.apache.org/beanutils/下载commons-beanutils-1.8.3-bin.zip 2.将其中的.jar导入工程 3.不采用BuildPath->添加外部归档方式导入工程,这样做.jar并不在工程目录下(例如在d:\下) 一旦将工程拷贝到其它机器下,还需要把该.jar拷贝到d:\下,不然用不了 解决方式:在工程下新建lib文件夹->将.jar拷贝到lib下->Build Path */
/* public static String getProperty(Object bean,String name)throws IllegalAccessException, InvocationTargetException, NoSuchMethodExceptionpublic static void setProperty(Object bean,String name,Object value) throws IllegalAccessException, InvocationTargetException*/public class BeanUtilsDemo { public static void main(String[] args)throws Exception { // TODO 自动生成的方法存根 Car car=new Car("black",20); //使用BeanUtils来set/get属性 String number=BeanUtils.getProperty(car,"number");//获取car对象color属性的值,注意返回值固定为String BeanUtils.setProperty(car,"color","red");//设置car对象number属性的值为4 BeanUtils.setProperty(car,"number","2");//传入2(自动装箱,内部需要拆箱)或"2"均可,"2"内部涉及到从String->int转换 System.out.println(car.getColor()+" "+car.getNumber()+"\n"); //级联属性设置与获取 BeanUtils.setProperty(car,"birthday.time","1000");//在Date类中一个public void setTime(long time)方法->属性time //通俗例子:设置person.head.face.eye.color System.out.println(BeanUtils.getProperty(car,"birthday.time")+"\n"); //JavaBean与Map相互转换 Map map=BeanUtils.describe(car);//会将JavaBean中 所有属性值 存入到Map中,前提是该属性值有对应get方法 System.out.println(map);//里面还有一个属性为字节码文件对象,也就是指定的JavaBean类 map=new HashMap(); map.put("color","blue"); map.put("number",2); map.put("birthday.time",200); BeanUtils.populate(car, map);//填充:将map中key对应javabean中的property,将其value赋给property System.out.println(car.getColor()+" "+car.getNumber()); System.out.println(BeanUtils.getProperty(car,"birthday.time")+"\n"); //PropertiesUtils工具类 PropertyUtils.setProperty(car,"number",13);//属性值的类型必须和Car中number类型一致均为int Object obj=PropertyUtils.getProperty(car, "number"); System.out.println(obj+" "+obj.getClass().getName());//说明上面的getProperty以Integer类型返回 } }/*不导入commons-logging-1.1.3.jar之前的运行结果:
Exception in thread "main" java.lang.NoClassDefFoundError:org/apache/commons/logging/LogFactory相当于有了电视机,但遥控器是第三方->电视机没法用需要导入遥控器->下载commons-logging(通用日志)并build path*/
1: package cn.itcast.feature;
2:
3: import java.lang.reflect.InvocationTargetException;
4: import java.text.ParseException;
5: import java.text.SimpleDateFormat;
6: import java.util.Date;
7:
8: import org.apache.commons.beanutils.BeanUtils;
9: import org.apache.commons.beanutils.ConversionException;
10: import org.apache.commons.beanutils.ConvertUtils;
11: import org.apache.commons.beanutils.Converter;
12: import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
13: import org.junit.Test;
14:
15: /*16: 虽然使用BeanUtils简化了代码量17: 但是BeanUtils默认只能帮你进行八大基本类型间的转换或18: String到八大基本类型转换.19: 如果我需要用到String->Date的转换,需要我们自定义转换器20: */21: public class CustomConvert {22: private Person p=new Person();23: @Test24: public void convertTest_1() throws IllegalAccessException, InvocationTargetException{25: BeanUtils.setProperty(p,"birthday","1980-3-1");26: System.out.println(p.getBirthday());27: }
28:
JUnit测试:2.这时候我们需要自定义转换器完成String->Date1: @Test2: public void convertTest_2() throws IllegalAccessException, InvocationTargetException{3: ConvertUtils.register(//注册一个自定义转换器完成String->Date转换4: new Converter() {5: @Override6: public Object convert(Class type, Object value) {7: // TODO Auto-generated method stub8: if (value == null)9: return null;10: if (!(value instanceof String))11: throw new ConversionException("不支持从"12: + value.getClass().getName() + "到"13: + type.getName() + "的转换");14: String valueStr = (String) value;
15: if ((valueStr = valueStr.trim()).equals(""))// 去除字符串首尾的空格,同时判断是否是空串16: return null;17:
18: // 开始转换工作,以上做的判断完全为了程序的健壮性19: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");20: try {21: return sdf.parse(valueStr);// 该方法有异常声明但是我不能在convert方法上进行声明,只能try...catch22: // 因为该匿名子类复写的Converter中的convert方法上没有任何异常声明23: } catch (ParseException e) {24: // TODO Auto-generated catch block25: throw new RuntimeException(e);26: }
27:
28: }
29:
30: }, Date.class);31: BeanUtils.setProperty(p,"birthday","1980-3-1");32: System.out.println(p.getBirthday());33: }
34:
3.如果把BeanUtils.setProperty(p,"birthday","1980-3-1");换成BeanUtils.setProperty("birthday",1980-3-1);不能通过测试:4.使用已提供的Sting->Date的转换器:1: @Test2: public void convertTest_3() throws IllegalAccessException, InvocationTargetException{3: //使用API提供的转换器:DateLocaleConverter4: ConvertUtils.register(new DateLocaleConverter(),Date.class);5: BeanUtils.setProperty(p,"birthday","1980-3-1");6: System.out.println(p.getBirthday());7:
8: //但是该转换器有Bug,那就是传入一个空串9: BeanUtils.setProperty(p,"birthday","");10: System.out.println(p.getBirthday());11: }
5.最后来看下throw new RuntimeException(e);打印的异常信息:1: @Test2: //throw new RuntimeException(Throwable cause);3: /*用指定的原因和详细消息 (cause==null ? null :cause.toString())4: 构造一个新的运行时异常(它通常包含类和 cause 的详细消息)。5: */6: //下面我们故意让parse抛出ParseException看下打印信息7: public void ParseExceptionTest(){8: try {9: System.out.println(new SimpleDateFormat("yyyy/MM/dd").parse("2014-1-17"));10: } catch (ParseException e) {11: // TODO Auto-generated catch block12: throw new RuntimeException(e);13: }
14: }
0 0
- 框架,JavaBeans与内省(Introspector)
- 黑马程序员_Java高新技术3(框架,JavaBeans与内省(Introspector)) - 伊秋
- 内省IntroSpector与JavaBean
- java反射与内省(Introspector)
- Java反射与内省(Introspector)
- Java反射与内省(Introspector)
- Java反射与内省(Introspector)
- Java反射与内省(Introspector)
- Java反射与内省(Introspector)
- Java反射与内省(Introspector)
- Java反射与内省(Introspector)
- 反射(reflect)、内省(introspector)以及BeanUtils框架
- 内省(Introspector)
- 内省(Introspector)
- 内省(Introspector)
- IntroSpector内省
- 内省(Introspector)
- Java反射(Reflection)与内省(Introspector)
- CCNode 的onEnter函数何时调用分析
- 作业2.30
- opengl 绘制拉框 不用重新绘制底图的方法
- Eclipse挂载Tomcat服务器发布项目
- C# IEnumerable<T>、IEnumerator<T>、List<T>、ArrayList、[]数组各各的区别
- 框架,JavaBeans与内省(Introspector)
- Objective-C中的常用数学常量宏及函数
- JavaWeb-13 (用户的注册和登录案例)
- C语言正则表达式详解 regcomp() regexec() regfree()详解
- getOutputStream() has already been called for this response异常的原因和解决方法
- nyoj-20-吝啬的国度-DFS+容器
- 模板模式
- 串口中怎样接收一个完整数据包的解析
- 2015考研调剂