1OOP进阶之一动态与反射文档格式.docx
《1OOP进阶之一动态与反射文档格式.docx》由会员分享,可在线阅读,更多相关《1OOP进阶之一动态与反射文档格式.docx(22页珍藏版)》请在冰点文库上搜索。
![1OOP进阶之一动态与反射文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/7/98d16e7f-4c86-4d35-9ac7-ef0d033c7e1b/98d16e7f-4c86-4d35-9ac7-ef0d033c7e1b1.gif)
4.IOC模式2构造注入(代理对象):
10
4.AOP代理分析:
11
5.IOC结构分析:
13
6.Struts/Hibernate/Spring实现原理分析14
总结和任务:
15
一切皆为对象!
1.java的类装载体系与动态载入
1.类装载基础
ClassLoader加载体系中的核心API:
Class,ClassLoader,Object
动态装载的关节点:
Class.forName(“要装载的类的名字“);
1)检查当前内存中是否有该类,若有直接返回,若无,请求父类的ClassLoader加载,如无父类,则从从bootstapclassloader加载,即JDK基本类库;
通过这种委托装载机保,保证每个类只被装载一次!
;
在编译或运行时,可能过-verbose标志查看装载的类。
2)具体分析java.lang.ClassLoader中的相关方法,这是一个抽像类---你可以重写它,从任意地方以字节流的行式加载需要的类到当前jvm中。
装载后执行顺序:
1.静态块执行;
--如不写main方法,执行程序?
2.创建对象后,属性赋值,非静态块执行.
3.初始化的过程:
父类-类static块属性-构造器?
常见的是程序中抛出java/lang/ClassNotFoundException:
...
则肯定是通过Class.forName(“ClassName”)时没有找到类。
如果把源码比做剧本,对象就是演员,JVM就是舞台。
静态编译:
在编译时确定类型,绑定对象,即通过。
动态编译:
运行时(RunningTime)确定类型,绑定对象。
动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性,即Class.forName(“ClassName”)应用。
为了继承以下示例,我们编写了简单的继承代码:
packageref;
/**
*机动车接口定义
*@author:
蓝杰
*/
publicinterfaceIVehicle{
publicvoidstartMe();
//启动
publicintforward(intdins);
//前进;
//有多少油
publicintgetEnergy();
}
//机动车实现类:
宝马车
publicclassBMWimplementsIVehicle{
publicstaticfinalStringcompany="
宝马公司"
;
publicintenergy;
//能量
publicBMW(){
this.energy=10;
}
publicBMW(intenergy){
this.energy=energy;
//启动
publicvoidstartMe(){
System.out.println("
BMW启动...."
);
//前进;
publicintforward(intdins){
energy-=dins/100;
BMW前进"
+dins);
returnenergy;
//有多少能量
publicintgetEnergy(){
returnthis.energy;
静态编译/静态绑定:
//静态绑定:
IVehiclevehicle=newBMW();
vehicle.forward(100);
动态编译/绑定/运行时多态:
//1.载入类对象
Classc=Class.forName("
ref.BMW"
//2.调用默认无参构造器生成对象
Objectobject=c.newInstance();
//3.强制转型
IVehicleve=(IVehicle)object;
ve.forward(500);
优点?
Reflection是Java被视为动态(或准动态)语言的一个关键性质。
这个机制允许程序在运行时通过ReflectionAPIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public,static等等)、superclass(例如Object)、实现的interfaces,也包括fields和methods的所有信息,并可于运行时改变fields内容或调用Constructor,methods。
BMWb=newBMW();
//判断对象所属的类型
if(binstanceofBMW){
System.out.println("
是BMW类型!
"
}
if(binstanceofIVehicle){
是IVehicle类型!
Classc=b.getClass();
StringclassName=c.getName();
System.out.println("
类的名字是:
"
+className);
//得到类中的方法对象数组
java.lang.reflect.Method[]methods=c.getMethods();
//得到类定义的构造器对象数组
java.lang.reflect.Constructor[]cons=c.getConstructors();
//得到类定义的属性对象数组
java.lang.reflect.Field[]fields=c.getFields();
//得到类的直接父类类对象
ClasssuperClass=c.getSuperclass();
//得到类所有实现的接口类对象数组
Class[]interfaces=c.getInterfaces();
privatestaticvoidprintFiledInfo(java.lang.reflect.Field[]fields){
共有属性:
+fields.length);
for(java.lang.reflect.Fieldf:
fields){
StringfName=f.getName();
属性名字是:
+fName);
ClassfType=f.getType();
属性类型是:
+fType);
//得到属性的访问限定符
intmType=f.getModifiers();
//判断是何种限定符
if(java.lang.reflect.Modifier.isPublic(mType))
public"
if(java.lang.reflect.Modifier.isAbstract(mType))
abstract"
if(java.lang.reflect.Modifier.isFinal(mType))
final"
//输出所有接口名字
privatestaticvoidprintInterface(Class[]interfaces){
for(Classc:
interfaces){
接口名:
+c.getName());
Class[]cs=c.getInterfaces();
printInterface(cs);
}
//输出所有父类名字
privatestaticvoidprintSuper(ClasssuperClass){
+superClass.getName());
Classss=superClass.getSuperclass();
if(null!
=ss){
printSuper(ss);
}
//打印方法信息
privatestaticvoidprintMethodInfo(java.lang.reflect.Method[]methods){
for(java.lang.reflect.Methodm:
methods){
intt=m.getModifiers();
限定符是:
+t);
Stringname=m.getName();
方法名是:
+name);
ClassreturnType=m.getReturnType();
返回值类型是:
+returnType.getName());
//参数类型组....
Classps[]=m.getParameterTypes();
//异常类型组...
Classes[]=m.getExceptionTypes();
//打印构造器信息
privatestaticvoidprintConstructorInfo(java.lang.reflect.Constructor[]cons){
for(java.lang.reflect.Constructorcon:
cons){
//构造器限定符
intm=con.getModifiers();
//得到参数类型表...
Class[]ptype=con.getParameterTypes();
BMWbm=createObj("
//根据类名字,用无参构造器创建类的对象
publicstaticBMWcreateObj(StringclassName){
try{
Objectobj=Class.forName(className).newInstance();
if(objinstanceofBMW){
BMWbm=(BMW)obj;
returnbm;
}catch(InstantiationExceptione){
System.out.println(e);
}catch(IllegalAccessExceptione){
}catch(ClassNotFoundExceptione){
returnnull;
3.2调用指定的构造器创建对象
通过前面对象的解析,我们可以得到类的构造器对象和其参数表,如下代码,即可调用指定的构造器创建对象:
/**
*调用有参数的构造器创建对象
*@paramconstructor:
构造器对象
*@paramarguments:
参数表
*@return:
创建好的对象
publicstaticObjectcreateObject(Constructorconstructor,
Object[]arguments){
Objectobject=null;
try{
object=constructor.newInstance(arguments);
Object:
+object.toString());
returnobject;
System.out.println(e);
}catch(IllegalAccessExceptione){
}catch(IllegalArgumentExceptione){
}catch(InvocationTargetExceptione){
returnobject;
调用方法前,必须己知方法的名字,方法参数类型,如下示:
*调用对象的方法
*@parambmw:
要调用的对象
*@paramdestName:
要调用的方法名字
*@paramparaType:
方法参数类型列表
publicstaticvoidinvokeTest(BMWbmw,StringdestName,Class...paraType){
//得到对象所在的类:
ClassdestClass=BMW.class;
//查询到要调用的方法对象
java.lang.reflect.MethoddestM=destClass.getMethod(destName,paraType);
if(null!
=destM){
//调用方法,传入参数
Objectobj=destM.invoke(bmw,300);
System.out.println(destM+"
调用结果是"
+obj);
}catch(Exceptionef){
ef.printStackTrace();
Class
Description
Array
提供动态(dynamically)创建、访问数组的类方法.
表述(Represents),反射(reflects)类或接口.
Constructor
提供访问或提取类的构造器的方法和动态创建类的方法.
Field
提供动态访问、设置类或接口域数据的方法.
Method
提供动态访问、调用类或接口的方法.
Modifier
提供静态方法提取类及其成员的modifiers信息.
Object
提供了一个getClass取得这个对象的类对象(classObject)
//BMW是实现了IVehicle接口的类
IVehiclev=newBMW();
//根据接口中定义的方法调用...
v.startMe();
图:
优点:
Client不必知道其使用对象的具体所属类。
一个对象可以很容易地被(实现了相同接口的)的另一个对象所替换。
对象间的连接不必硬绑定(hardwire)到一个具体类的对象上,因此增加了灵活性。
松散藕合(loosenscoupling);
增加了重用的可能性。
工厂类一般为单态模式:
classVehicleFactory{
//最简单的工厂方法
publicIVehiclecreateIVehicle(StringclassName){
IVehiclev=(IVehicle)Class.forName(className).newInstance();
returnv;
returnv;
IOC:
InversionofControlDI:
DependencyInjection
publicinterfaceDriver{
publicvoidsetVehicle(IVehiclevehicle);
publicvoidgo();
//userCode:
publicvoidtest(IVehiclev,Driverd){
d.setVehicle(v);
d.go();
如图示例:
基实是包装器的设计思路:
classBigBM()implementsIVehicle{
privateIVehiclev;
publicBigBM(IVehiclev){
this.v=v;
超级宝马启动!
!
publicvoidtest(IVehiclev){
BigBMb=newBigBM(v);
b.startMe();
如下图示:
考虑javaIOAPI中过滤器流的设计,就是这种实现方式。
以上都无法解决的问题:
源码级藕合!
4.AOP代理实现:
同现实中“代理”一词的意思相同:
比如我要去买保险,要调用的关键方法只有一个:
传入人民币,拿到保单;
但这其中还有很多跟我关注的核心方法无关的动作执行,如填写资料表,审核资料,提交证明...与是,我通过一个保险代理人来买保险---通过代理对象执行我需要的调用----我就可专注于自己想要的东东了。
调用一个对象的方法时,可通这调用这个对象的“代理对象“执行,如果某些方法要日志记录,事务管理,审计…,就只需修改代理类中的方法,而不必修改对象“原类”中的代码。
要实现这一功能,必须先编写一个通用的代理类,如下:
importjava.lang.reflect.InvocationTargetException;
importjava.lang.reflect.Method;
*通用的代理类实现
publicclassDebugVehicleProxyimplementsjava.lang.reflect.InvocationHandler{
//被代理的对象
privateObjectobj;
//得到代理对象
publicstaticObjectgetProxy(Objectobj){
returnjava.lang.reflect.Proxy.newProxyInstance(obj.getClass()
.getClassLoader(),obj.getClass().getInterfaces(),
newDebugVehicleProxy(obj));
privateDebugVehicleProxy(Objectobj){
this.obj=obj;
*实现InvocationHandler中的方法
*被代理类调用时,实际上是通过这个方法调用的
*@paramproxy:
被调用方法的对象
*@paramm:
要调用的方法对象
*@paramargs:
调用方法的参数列表
publicObjectinvoke(Objectproxy,Methodm,Object[]args)throwsThrowable{
Objectresult;
debugadvicebegin:
+m.getName());
result=m.invoke(obj,args);
//调用实际对象的方法
throwe.getTargetException();
}catch(Exceptione){
thrownewRuntimeException("
invocation:
+e.getMessage());
}finally{
debugadvicefinash:
returnresult;
测试通过代理对象调用对象的方法:
publicclassDriver{
publicstaticvoidmain(Stringargs[]){
IVehiclesrcv=newBMW();
//代理前执行:
srcv.forward(100);
//通过代理对象执行
IVehiclev=(IVehicle)DebugVehicleProxy.getProxy(s