今天的内容是Java基础加强,主要讲解了反射和动态代理,是为以后学习三大框架打基础,虽然在三大框架的应用中反射和动态代理使用的不多,但是在三大框架的底层编写中使用的非常广泛,掌握好了反射和动态代理,对于更好的了解三大框架原理有很大的帮助,学习框架主要就是学习原理,不懂原理照猫画虎是不会有什么提高的。反射还好说,在就业班开始的时候毕老师已经带我们接触过了,动态代理就不是很好理解了,还得多研究一下。
反射
通过反射获取class对象的三种方式
使用Class的forName()静态方法 最常用 例:Class.forName(“cn.itcast.person”);
调用某个类的class属性 效率最高 例: Class personClass = Person.class
调用某个对象的getClass方法 例: Person p = new Person(); Class personClass = p.getClass();
获取到class对象后就可以调用class对象方法获取该对象和该类的详细信息。
创建类的实例:
1使用 Class对象的 newInstance()方法来创建Class对象对应类的实例, 这种方式要求该 Class 对象的对应类有默认的构造器, 而执行 newInstance() 方法时实际上时利用默认的构造器来创建该类的实例
2先使用 Class 对象获取指定的 Constructor 对象, 再调用 Constructor 对象的 newInstance() 方法来创建该 Class 对象对应类的实例. 通过这种方式可以选择使用某个类的指定的构造器来创建实例
调用类的方法:
当获取某个类对应的 Class 对象后, 就可以通过 Class 对象的 getMethods() 或 getMethod() 方法来获取全部方法或指定的方法.每个 Method 对象对应一个方法, 获得 Method 对象后, 程序就可通过该 Method 类的invoke()方法来调用对应方法.
访问属性值:
通过 Class 对象的 getFields () 或 getField() 方法可以获取该类所包括的全部 Field 或指定的 Field . 注意getFields ()方法返回 Field
对象的一个数组,这些对象反映此 Class
对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。
内省
内省是 Java 语言对 Bean 类属性的一种缺省处理方法。例如类 A 中有属性 name, 可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这是默认的规则。 Java 中提供了一套 API 来访问某个属性的 getter/setter 方法。
一般的做法是通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法
Beanutils 用法
BeanUtils是commons-beanutils-bin.zip包里比较常用的一个工具类,该类有一个copyProperties() 属性复制方法。该方法定义如下:
public static void
copyProperties(java.lang.Object,dest,java.lang.Object orig)
如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm,例如 Teacher和TeacherForm。我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是对属性逐个赋值,使用BeanUtil我们就可以通过转换器完成。
ConvertUtils.regsiter(Converter convert, Class clazz) 注册转换器
BeanUtil中支持的转换类型不包括java.util.Date,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常.
动态代理
Proxy 提供用于创建动态代理类和代理对象的静态方法, 它也是所有动态代理类的父类.
Proxy 提供了两个方法来创建动态代理类和动态代理实例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler{
private Object targerObject;//代理的目标对象
/**
* 创建代理对象
* @param targerObject 目标对象
* @return
*/
public Object createProxyInstance(Object targerObject){
this.targerObject=targerObject;
/*
* 第一个参数设置代码使用的类加载器,一般采用跟目标类相同的类加载器
* 第二个参数设置代理类实现的接口,跟目标类使用相同的接口
* 第三个参数设置回调对象,当代理对象的方法被调用时,会调用该参数指定对象的invoke方法
*/
return Proxy.newProxyInstance(targerObject.getClass().getClassLoader(),
targerObject.getClass().getInterfaces(), this);
}
/**
* @param proxy 目标对象的代理类实例
* @param method 对应于在代理实例上调用接口方法的Method实例
* @param args 传入到代理实例上方法参数值的对象数组
* @return 方法的返回值 没有返回值时是null
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("代理类实例 "+proxy.getClass());
System.out.println("方法名称 "+method.getName());
if(args!=null&&args.length>0){//方法的参数值
for(int i=0;i<args.length;i++){
System.out.println("方法参数值 "+args[i].toString()); } }
Object returnvalue=null; //定义方法的返回值 没有返回值时是null
returnvalue=method.invoke(this.targerObject, args); //调用目标对象的方法
System.out.println("方法的返回值 "+returnvalue);
return returnvalue;
}
}