Java反射和动态代理

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

JavaWeb分层架构类一、类的生命周期在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开JVM。在程序执行中JVM通过装载,链接,初始化这3个步骤完成。1、类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的java.lang.Class对象。用来封装数据。但是同一个类只会被类装载器装载以前链接就是把二进制数据组装为可以运行的状态。2、链接分为校验,准备,解析这3个阶段a)校验一般用来确认此二进制文件是否适合当前的JVM(版本);b)准备就是为静态成员分配内存空间,并设置默认值。c)解析指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)。3、完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。当没有任何引用指向Class对象时就会被卸载,结束类的生命周期。二、类加载器在java中有三种类类加载器。1)BootstrapClassLoader此加载器采用c++编写,一般开发中很少见。2)ExtensionClassLoader用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类3)AppClassLoader加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。反射一、反射的概念:主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。通常我们创建一个对象,只需要一句话new,但是new的前提是在知道类名的情况下,如果不知道类名,怎么得到这个类的对象呢?其实我们可以通过反射来实现。一个Java程序在运行时,可以获得任何一个类的字节码信息,包括类的修饰符(public,static等),基类(超类,父类),实现的接口,字段,方法等信息。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并逆向生成其对象实体、或对其fields设值、或唤起其methods。那么java是怎么实现这种机制的呢?Java的反射机制是通过反射API来实现的,主要包括以下几类:1).Constructor类:用来描述一个类的构造方法2).Field类:用来描述一个类的成员变量3).Method类:用来描述一个类的方法.4).Modifer类:用来描述类内各元素的修饰符5).Array:用来对数组进行操作.Constructor,Field,Method这三个类都是JVM(虚拟机)在程序运行时创建的,用来表示加载类中相应的成员。也就是说可以通过这些类来获取和改变反射类的所有成员。反射在框架中是最常用的手段。一个框架是先于调用者而存在的。当程序员用一个框架的时候,你写的什么类,框架怎么知道,就是通过java反射机制。Web.xml、Struts2.xml、applicationContext.xml、hibernate.cfg.xml、Peroson.hbm.xml、sqlMapperConfig.xml、PersonMapper.xml等配置文件中的class对应的字节码,都是通过反射来创建对象的。Param标签中的参数也是通过反射将其值设置到对象中。一个标准的javaBean的反射叫做内省。mybatis的resultMap标签中,把结果集的和PO对象的属性一一对应起来,就能把结果集赋值给PO对象,这也是通过反省实现的。通过mapper.xml中指定的type,得到PO对象。二、反射机制的作用:1、反编译:.class--.java2、通过反射机制访问java对象的属性,方法,构造方法等;这样好像更容易理解一些,下边我们具体看怎么实现这些功能。三、SUN提供的有关反射机制中的类java.lang.Class;java.lang.reflect.Constructor;java.lang.reflect.Field;java.lang.reflect.Method;java.lang.reflect.Modifier;很多反射中的方法,属性等操作我们可以从这四个类中查询。还是哪句话要学着不断的查询API,那才是我们最好的老师。四、具体功能实现1、反射机制获取类有三种方法,我们来获取Employee类型1.//第一种方式:2.Classc1=Class.forName(Employee);3.//第二种方式:4.//java中每个类型都有class属性.5.Classc2=Employee.class;6.7.//第三种方式:8.//java语言中任何一个java对象都有getClass方法9.Employeee=newEmployee();10.Classc3=e.getClass();//c3是运行时类(e的运行时类是Employee)2、创建对象:获取类以后我们来创建它的对象,利用newInstance:1.Classc=Class.forName(Employee);2.3.//创建此Class对象所表示的类的一个新实例4.Objecto=c.newInstance();//调用了Employee的无参数构造方法.3、获取属性:分为所有的属性和指定的属性:a,先看获取所有的属性的写法://获取整个类1.Classc=Class.forName(java.lang.Integer);2.//获取所有的属性?3.Field[]fs=c.getDeclaredFields();4.5.//定义可变长的字符串,用来存储属性6.StringBuffersb=newStringBuffer();7.//通过追加的方法,将每个属性拼接到此字符串中8.//最外边的public定义9.sb.append(Modifier.toString(c.getModifiers())+class+c.getSimpleName()+{\n);10.//里边的每一个属性11.for(Fieldfield:fs){12.sb.append(\t);//空格13.sb.append(Modifier.toString(field.getModifiers())+);//获得属性的修饰符,例如public,static等等14.sb.append(field.getType().getSimpleName()+);//属性的类型的名字15.sb.append(field.getName()+;\n);//属性的名字+回车16.}17.18.sb.append(});19.20.System.out.println(sb);b,获取特定的属性,对比着传统的方法来学习:1.publicstaticvoidmain(String[]args)throwsException{2.3.spanstyle=white-space:pre/span//以前的方式:4./*5.Useru=newUser();6.u.age=12;//set7.System.out.println(u.age);//get8.*/9.10.//获取类11.Classc=Class.forName(User);12.//获取id属性13.FieldidF=c.getDeclaredField(id);14.//实例化这个类赋给o15.Objecto=c.newInstance();16.//打破封装17.idF.setAccessible(true);//使用反射机制可以打破封装性,导致了java对象的属性不安全。18.//给o对象的id属性赋值11019.idF.set(o,110);//set20.//get21.System.out.println(idF.get(o));22.}4、获取属性、方法,和构造方法属性关键字含义FiledgetField(Stringname)返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段。Filed[]getFiled()返回一个包含某些Field对象的数组,这些对象反映此Class对象所表示的类或接口的所有可访问公共字段。FiledgetDeclaredField(Stringname)返回一个Field对象,该对象反映此Class对象所表示的类或接口的指定已声明字段。Filed[]getDeclaredFiled()返回Field对象的一个数组,这些对象反映此Class对象所表示的类或接口所声明的所有字段。方法关键字含义getDeclaredMethods()获取所有的方法getReturnType()获得方法的返回类型getParameterTypes()获得方法的传入参数类型getDeclaredMethod(方法名,参数类型.class,……)获得特定的方法构造方法关键字含义getDeclaredConstructors()获取所有的构造方法getDeclaredConstructor(参数类获取特定的构造方法型.class,……)父类和父接口含义getSuperclass()获取某类的父类getInterfaces()获取某类实现的接口这样我们就可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。五、反射加配置文件,使我们的程序更加灵活在设计模式学习当中,学习抽象工厂的时候就用到了反射来更加方便的读取数据库链接字符串等,当时不是太理解,就照着抄了。看一下.NET中的反射+配置文件的使用:当时用的配置文件是app.config文件,内容是XML格式的,里边填写链接数据库的内容:configuration1.lt;appSettings2.addkey=value=/3.lt;/appSettings4./configuration反射的写法:1.assembly.load(当前程序集的名称).CreateInstance(当前命名空间名称.要实例化的类名);这样的好处是很容易的方便我们变换数据库,例如我们将系统的数据库从SQLServer升级到Oracle,那么我们写两份D层,在配置文件的内容改一下,或者加条件选择一下即可,带来了很大的方便。当然了,JAVA中其实也是一样,只不过这里的配置文件为.properties,称作属性文件。通过反射读取里边的内容。这样代码是固定的,但是配置文件的内容我们可以改,这样使我们的代码灵活了很多!综上为,JAVA反射的再次学习,灵活的运用它,能够使我们的代码更加灵活,但是它也有它的缺点,就是运用它会使我们的软件的性能降低,复杂度增加,所以还要我们慎重的使用它。六、反射实现动态调用方法1、创建UserDao接口2、创建UserDaOracleImpl实现类3、创建UserDaoMySQLImpl实现类4、创建TestUserDao测试类代理模式代理模式是常用的Java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理的创建时期,代理类可以分为两种。静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理:在程序运行时,运用反射机制动态创建而成。静态代理由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。静态代理的实现步骤1、创建一个UserDao接口2、创建UserDaoMySQLImpl实现类3、创建UserDa

1 / 25
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功