日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

支撑Java框架的基础技术:泛型,反射,动态代理,cglib

發(fā)布時(shí)間:2023/11/27 生活经验 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 支撑Java框架的基础技术:泛型,反射,动态代理,cglib 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

以Spring為例要想看明白他的源碼需要徹底理解Java的一些基礎(chǔ)技術(shù)泛型,反射同時(shí)對(duì)于一些高級(jí)技術(shù)例如動(dòng)態(tài)代理,cglib和字節(jié)碼技術(shù)也需要掌握,下面就按章節(jié)來(lái)一一說(shuō)清楚這些技術(shù)的核心部分,最后手寫(xiě)一個(gè)簡(jiǎn)單的Spring框架。

?

一.靜態(tài)代碼塊和非靜態(tài)代碼塊以及構(gòu)造函數(shù)的調(diào)用順序

?

靜態(tài)代碼塊:https://stackoverflow.com/questions/2420389/static-initialization-blocks

每次構(gòu)造類(lèi)的實(shí)例時(shí)都會(huì)調(diào)用它。在靜態(tài)塊只被調(diào)用一次,當(dāng)類(lèi)本身初始化,無(wú)論你如何創(chuàng)建該類(lèi)型的許多對(duì)象。

例子二:?

?

下面這個(gè)例子用于演示完整的代碼調(diào)用順序。

先看父類(lèi):?

public class Parent {static String name = "hello";//非靜態(tài)代碼塊{System.out.println("1");}//靜態(tài)代碼塊static {System.out.println("2");}public Parent() {System.out.println("3");}
}

再看子類(lèi):

public class Child extends Parent {static String childName = "hello";{System.out.println("4");}static {System.out.println("5");}public Child() {System.out.println("6");}
}

調(diào)用測(cè)試的主函數(shù):

public class StaticCodeBlockOrderTest {public static void main(String[] args) {new Child();}
}

輸出:

?

對(duì)象的初始化順序:
首先執(zhí)行父類(lèi)靜態(tài)的內(nèi)容,父類(lèi)靜態(tài)的內(nèi)容執(zhí)行完畢后,接著去執(zhí)行子類(lèi)的靜態(tài)的內(nèi)容,當(dāng)子類(lèi)的靜態(tài)內(nèi)容執(zhí)行完畢之后,再去看父類(lèi)有沒(méi)有非靜態(tài)代碼塊,
如果有就執(zhí)行父類(lèi)的非靜態(tài)代碼塊,父類(lèi)的非靜態(tài)代碼塊執(zhí)行完畢,接著執(zhí)行父類(lèi)的構(gòu)造方法;父類(lèi)的構(gòu)造方法執(zhí)行完畢之后,它接著去看子類(lèi)有沒(méi)有非靜態(tài)代碼塊,如果有就執(zhí)行子類(lèi)的非靜態(tài)代碼塊。
子類(lèi)的非靜態(tài)代碼塊執(zhí)行完畢再去執(zhí)行子類(lèi)的構(gòu)造方法。

參考:java中靜態(tài)代碼塊的用法 static用法詳解
?

靜態(tài)代碼塊的應(yīng)用場(chǎng)景:

需要一個(gè)Util類(lèi),需要系統(tǒng)初始化的時(shí)候就初始化一個(gè)hashMap,部分代碼省略以...代替

?

    private static Map<String, List<String>> smap = new HashMap<String, List<String>>();static {for (int i = 0; i < k; i++) {List<String> ls = new ArrayList<String>();ls.add(...);ls.add(...);smap.put(..., ls);}}

?

這個(gè)一樣的用法:Map的靜態(tài)賦值?

?

二.泛型:

?

這個(gè)老外的視頻講的很好《Java Generics》

E - Element (在集合中使用,因?yàn)榧现写娣诺氖窃?
T - Type(Java 類(lèi))
K - Key(鍵)
V - Value(值)
N - Number(數(shù)值類(lèi)型)
? - ?表示不確定的java類(lèi)型

1.泛型類(lèi)

https://blog.csdn.net/weixin_43819113/article/details/91042598

https://www.cnblogs.com/coprince/p/8603492.html

泛型類(lèi)有普通方法返回T,和泛型方法<T> T。

?

2.泛型方法

泛型方法可以不用是泛型類(lèi) ,有泛型參數(shù)需要才是泛型方法返回值之前需要泛型參數(shù)

static 后的<E>是泛型聲明,這樣才可以在這個(gè)方法參數(shù)和方法體用泛型

static <E>后的Set<E>是返回值

泛型類(lèi):?

不用泛型需要強(qiáng)轉(zhuǎn):?

輸出:

[123, 456, 789]
[123, 456, 789, 123, 456, 789]
[123, 456, 789]

?

3.泛型 Class<T>和Class<?>的差異

?

public class Box<T> {private T t;public Box(){}public Box(T data){this.t=data;}public T getT() {return t;}public void setT(T t) {this.t = t;}
}

調(diào)用

?

?

    public static void main(String[] args) {Box<String> s=new Box<String>("abc");Box<Integer> i=new Box<Integer>(123);System.out.println("s class:" + s.getClass());System.out.println("i class:" + i.getClass());System.out.println(s.getClass() == i.getClass());
}

輸出

?

?

為什么有Class<T>還需要Class<?>呢?

其實(shí)看這個(gè)就明白了
在其他類(lèi)中例如這個(gè)Test里,你可以定義

?

    public static void getData(Box<String> data){System.out.println("data :" + data.getT());}


也可以定義

?

    public static void getData(Box<Integer> data){System.out.println("data :" + data.getT());}

?

?

但是你要是同時(shí)定義這2個(gè)就會(huì)報(bào)錯(cuò)

名稱(chēng)沖突: getData(Box<Integer>)和getData(Box<String>)具有相同疑符


?

使用通配符?就可以解決這個(gè)問(wèn)題

?

public class TestMain {public static void main(String[] args) {Box<String> s=new Box<String>("abc");Box<Integer> i=new Box<Integer>(123);System.out.println("s class:" + s.getClass());System.out.println("i class:" + i.getClass());System.out.println(s.getClass() == i.getClass());getData(s);getData(i);}public static void getData(Box<?> data){System.out.println("data :" + data.getT());}
}

?

?

參考:

Java總結(jié)篇系列:Java泛型

java中的泛型總結(jié)

?

再來(lái)看看Class<?>的用處

public class TestMain {public static void main(String[] args) {Box<String> s=new Box<String>("http://blog.csdn.net/unix21");Box<Integer> i=new Box<Integer>(123);System.out.println("s class:" + s.getClass());System.out.println("i class:" + i.getClass());System.out.println(s.getClass() == i.getClass());getData(Box.class);}public static void getData(Class<?> clz){try {System.out.println(clz);System.out.println("clz.hashCode():" + clz.hashCode());Object o=clz.newInstance();o.hashCode();System.out.println("o.hashCode():" + o.hashCode());} catch (Exception e) {  System.out.println(e);  }  }
}

?

((Box)clz).getT();會(huì)報(bào)錯(cuò):

不能將 "class java.lang.Class (no class loader)" 的實(shí)例強(qiáng)制轉(zhuǎn)換為 "class test.Box (loaded by instance of sun.misc.Launcher$AppClassLoader(id=144))" 的實(shí)例

說(shuō)明還沒(méi)有class loader

((Box)o).getT();就已經(jīng)實(shí)例化了。

?

4.Object類(lèi)型

定義的所有類(lèi)默認(rèn)都是子類(lèi),所有的類(lèi)都是以標(biāo)準(zhǔn)類(lèi)Object為基礎(chǔ),Object類(lèi)型的變量可以存儲(chǔ)指向任意類(lèi)類(lèi)型對(duì)象的索引。

當(dāng)要為一個(gè)方法來(lái)處理未知類(lèi)型的對(duì)象時(shí),這很有用。

?

//存儲(chǔ)的地方HashMap<String , Object> map = new HashMap<String , Object>();User u1=new User();u1.setId(1);u1.setName("ww1");//Object可以塞任意類(lèi)型map.put("user",u1);User u=(User)map.get("user");response.getWriter().println("Hello Servlet >>>"+u.getName());String clazz ="com.w1.User"; //bean.getAttributeValue("class");try {//反射Object o = Class.forName(clazz).newInstance();map.put("user2",o);User u2=(User)map.get("user2");u2.setName("ww223");response.getWriter().println("Hello Servlet >>>"+u2.getName());} catch (Exception e) {e.printStackTrace();}

?

三.反射

反射可以參考本人的反射深入專(zhuān)貼:深入淺出Java反射原理和使用場(chǎng)景

這里限于篇幅只羅列一點(diǎn)精華內(nèi)容。

類(lèi)名.class, class.forName(), getClass()區(qū)別

1:Class cl=A.class; ?
JVM將使用類(lèi)A的類(lèi)裝載器, 將類(lèi)A裝入內(nèi)存(前提是:類(lèi)A還沒(méi)有裝入內(nèi)存),不對(duì)類(lèi)A做類(lèi)的初始化工作.返回類(lèi)A的Class的對(duì)象。
2:Class cl=對(duì)象引用o.getClass();
返回引用o運(yùn)行時(shí)真正所指的對(duì)象(因?yàn)?子對(duì)象的引用可能會(huì)賦給父對(duì)象的引用變量中)所屬的類(lèi)的Class的對(duì)象 。
3:Class.forName("類(lèi)名");
.裝入類(lèi)A,并做類(lèi)的初始化
.getClass()是動(dòng)態(tài)的,其余是靜態(tài)的。
.class和class.forName()只能返回類(lèi)內(nèi)field的默認(rèn)值,getClass可以返回當(dāng)前對(duì)象中field的最新值
Class.forName() 返回的是一個(gè)類(lèi),.newInstance() 后才創(chuàng)建一個(gè)對(duì)象,Class.forName()的作用是要求JVM查找并加載指定的類(lèi),也就是說(shuō)JVM會(huì)執(zhí)行該類(lèi)的。

public class Person {private String name = "Alfira";public void getName() {System.out.println(name);}public void setName(String name, int a) {this.name = name + a;}
}

?

    private static void show(String name) {try {// JVM將使用類(lèi)A的類(lèi)裝載器,將類(lèi)A裝入內(nèi)存(前提是:類(lèi)A還沒(méi)有裝入內(nèi)存),不對(duì)類(lèi)A做類(lèi)的初始化工作Class classtype3 = Person.class;// 獲得classtype中的方法Method getMethod3 = classtype3.getMethod("getName", new Class[] {});Class[] parameterTypes3 = { String.class, int.class };Method setMethod3 = classtype3.getMethod("setName", parameterTypes3);// 實(shí)例化對(duì)象,因?yàn)檫@一句才會(huì)輸出“靜態(tài)初始化”以及“初始化”O(jiān)bject obj3 = classtype3.newInstance();// 通過(guò)實(shí)例化后的對(duì)象調(diào)用方法getMethod3.invoke(obj3); // 獲取默認(rèn)值setMethod3.invoke(obj3, "Setting new ", 3); // 設(shè)置getMethod3.invoke(obj3); // 獲取最新System.out.println("----------------");// 返回運(yùn)行時(shí)真正所指的對(duì)象Person p = new Person();Class classtype = p.getClass();// Class.forName(name);// 獲得classtype中的方法Method getMethod = classtype.getMethod("getName", new Class[] {});Class[] parameterTypes = { String.class, int.class };Method setMethod = classtype.getMethod("setName", parameterTypes);getMethod.invoke(p);// 獲取默認(rèn)值setMethod.invoke(p, "Setting new ", 1); // 設(shè)置getMethod.invoke(p);// 獲取最新System.out.println("----------------");// 裝入類(lèi),并做類(lèi)的初始化Class classtype2 = Class.forName(name);// 獲得classtype中的方法Method getMethod2 = classtype2.getMethod("getName", new Class[] {});Class[] parameterTypes2 = { String.class, int.class };Method setMethod2 = classtype2.getMethod("setName", parameterTypes2);// 實(shí)例化對(duì)象Object obj2 = classtype2.newInstance();// 通過(guò)實(shí)例化后的對(duì)象調(diào)用方法getMethod2.invoke(obj2); // 獲取默認(rèn)值setMethod2.invoke(obj2, "Setting new ", 2); // 設(shè)置getMethod2.invoke(obj2); // 獲取最新System.out.println("----------------");} catch (Exception e) {System.out.println(e);}}


調(diào)用

show("com.Person");


參考此文:http://www.cnblogs.com/feiyun126/archive/2013/08/01/3229492.html

http://blog.163.com/granite8@126/blog/static/853746082008610102657141/

?

四.JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理的區(qū)別

?

https://stackoverflow.com/questions/10664182/what-is-the-difference-between-jdk-dynamic-proxy-and-cglib

JDK動(dòng)態(tài)代理只能通過(guò)接口代理(因此您的目標(biāo)類(lèi)需要實(shí)現(xiàn)一個(gè)接口,然后由代理類(lèi)實(shí)現(xiàn))。

CGLIB(和javassist)可以通過(guò)子類(lèi)創(chuàng)建代理。在這種情況下,代理成為目標(biāo)類(lèi)的子類(lèi)。不需要接口。

所以Java動(dòng)態(tài)代理可以代理:public class Foo implements iFooCGLIB可以代理的地方:public class Foo

?

我應(yīng)該提一下,因?yàn)閖avassist和CGLIB通過(guò)子類(lèi)化使用代理,這就是你在使用依賴(lài)于它的框架時(shí)不能聲明?final方法或使類(lèi)?final的原因。這將阻止這些庫(kù)允許子類(lèi)化您的類(lèi)并覆蓋您的方法。

?

還應(yīng)該注意的是,CGLib子類(lèi)創(chuàng)建需要足夠了解超類(lèi),以便能夠使用正確的args調(diào)用正確的構(gòu)造函數(shù)。與基于接口的代理不同,它不關(guān)心構(gòu)造函數(shù)。這使得使用CGLib代理比JDK代理更少“自動(dòng)”。另一個(gè)區(qū)別在于“堆疊”成本。JDK代理總是在每次調(diào)用時(shí)產(chǎn)生額外的堆棧幀,而CGLib可能不會(huì)花費(fèi)任何額外的堆棧幀。隨著應(yīng)用程序越復(fù)雜,這變得越來(lái)越相關(guān)(因?yàn)槎褩T酱?#xff0c;內(nèi)存線程消耗越多)。

?

CGLIB不能代理?final方法,但不會(huì)拋出異常gist.github.com/mhewedy/7345403cfa52e6f47563f8a204ec0e80?-??Muhammad Hewedy?

?

使用CGLIB庫(kù)動(dòng)態(tài)創(chuàng)建代理

CGLIB庫(kù)是ASM之上的高級(jí)層。它對(duì)代理不實(shí)現(xiàn)接口的類(lèi)非常有用。本質(zhì)上,它動(dòng)態(tài)生成一個(gè)子類(lèi)來(lái)覆蓋代理類(lèi)的非final方法,并連接回調(diào)用戶(hù)定義的攔截器的鉤子。它比JDK動(dòng)態(tài)代理方法更快。

CGLIB是一個(gè)功能強(qiáng)大的高性能代碼生成庫(kù)。它是JDK動(dòng)態(tài)代理的補(bǔ)充,因?yàn)樗峁┝瞬粚?shí)現(xiàn)接口的代理類(lèi)。在封面下,它使用ASM字節(jié)碼操作框架。實(shí)質(zhì)上,CGLIB動(dòng)態(tài)生成一個(gè)子類(lèi)來(lái)覆蓋代理類(lèi)的非final方法。它比使用Java反射的JDK動(dòng)態(tài)代理方法更快。CGLIB不能使用任何最終方法代理最終類(lèi)或類(lèi)。對(duì)于一般情況,您使用JDK動(dòng)態(tài)代理方法來(lái)創(chuàng)建代理。當(dāng)接口不可用或性能問(wèn)題時(shí),CGLIB是一個(gè)很好的選擇。

?

https://stackoverflow.com/questions/4411129/why-does-jdk-dynamic-proxy-only-work-with-interfaces

https://www.quora.com/In-Java-why-are-dynamic-proxies-only-allowed-to-proxy-interface-classes

我相信這個(gè)決定是在Java標(biāo)準(zhǔn)庫(kù)中故意做出的,以支持接口而不是類(lèi)繼承。使用接口允許以不同方式引用相同的代理對(duì)象。

近年來(lái),它也是Java最佳實(shí)踐(或“類(lèi)似Java”),它將對(duì)象稱(chēng)為接口類(lèi)型而不是類(lèi),甚至是匿名類(lèi)。匿名類(lèi)通常用作擴(kuò)展的基礎(chǔ) - 因此成語(yǔ)類(lèi)C擴(kuò)展BaseC實(shí)現(xiàn)InterfaceC。

對(duì)于更高級(jí)的用法,例如增強(qiáng)現(xiàn)有類(lèi),使用第三方庫(kù)是可以接受的,因?yàn)檫@通常不是由最終用戶(hù)開(kāi)發(fā)人員完成的,而是由框架(例如Spring Framework)使用。

http://cliffmeyers.com/blog/2006/12/29/spring-aop-cglib-or-jdk-dynamic-proxies.html

即使您不是面向方面編程的忠實(shí)粉絲,如果您使用Spring框架的事務(wù)管理,您的應(yīng)用程序?qū)⑹褂脛?dòng)態(tài)AOP代理,盡管是在幕后。Spring可以使用兩種
不同的技術(shù)在運(yùn)行時(shí)創(chuàng)建代理:CGLIB或JDK動(dòng)態(tài)代理。

如果目標(biāo)類(lèi)實(shí)現(xiàn)了一個(gè)或多個(gè)接口,那么Spring將創(chuàng)建一個(gè)實(shí)現(xiàn)每個(gè)接口的JDK動(dòng)態(tài)代理。如果目標(biāo)類(lèi)沒(méi)有實(shí)現(xiàn)接口,Spring將使用CGLIB動(dòng)態(tài)創(chuàng)建一個(gè)新類(lèi),它是目標(biāo)類(lèi)的子類(lèi)(“extends”)。這導(dǎo)致了一個(gè)重要的區(qū)別:JDK動(dòng)態(tài)代理無(wú)法轉(zhuǎn)換為原始目標(biāo)類(lèi),因?yàn)樗皇且粋€(gè)動(dòng)態(tài)代理,恰好實(shí)現(xiàn)了與目標(biāo)相同的接口。如果在應(yīng)用程序的模型中使用它們,這會(huì)“輕推”您對(duì)接口進(jìn)行編程,因?yàn)橥ǔ?huì)通過(guò)這些接口調(diào)用代理。?

另一方面,如果模型中完全沒(méi)有接口,Spring將創(chuàng)建CGLIB代理,可以像目標(biāo)類(lèi)本身一樣對(duì)待或多或少。還有一種方式,迫使其在Spring文檔詳細(xì)介紹這兩種情況下CGLIB代理的創(chuàng)作就在這里。

http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html

使用Java Reflection可以在運(yùn)行時(shí)創(chuàng)建接口的動(dòng)態(tài)實(shí)現(xiàn)。你這樣做是使用這個(gè)類(lèi)java.lang.reflect.Proxy。這個(gè)類(lèi)的名稱(chēng)就是我將這些動(dòng)態(tài)接口實(shí)現(xiàn)稱(chēng)為動(dòng)態(tài)代理的原因。動(dòng)態(tài)代理可用于許多不同的目的,例如數(shù)據(jù)庫(kù)連接和事務(wù)管理,用于單元測(cè)試的動(dòng)態(tài)模擬對(duì)象,以及其他類(lèi)似AOP的方法攔截目的。

已知?jiǎng)討B(tài)代理至少用于以下目的:

  • 數(shù)據(jù)庫(kù)連接和事務(wù)管理
  • 用于單元測(cè)試的動(dòng)態(tài)模擬對(duì)象
  • DI容器適應(yīng)自定義工廠接口
  • 類(lèi)似AOP的方法攔截

https://www.logicbig.com/tutorials/core-java-tutorial/java-dynamic-proxies/runtime-interface-implementation.html

https://javax0.wordpress.com/2016/01/20/java-dynamic-proxy/

Java和CGLIB動(dòng)態(tài)代理

?

下面舉例演示使用方法:

public class SayHello {public void say(){System.out.println("hello everyone");}
}

?

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public Object getProxy(Class clazz) {//設(shè)置需要?jiǎng)?chuàng)建子類(lèi)的類(lèi)enhancer.setSuperclass(clazz);enhancer.setCallback(this);//通過(guò)字節(jié)碼技術(shù)動(dòng)態(tài)創(chuàng)建子類(lèi)實(shí)例return enhancer.create();}//實(shí)現(xiàn)MethodInterceptor接口方法public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("前置代理");//通過(guò)代理類(lèi)調(diào)用父類(lèi)中的方法Object result = proxy.invokeSuper(obj, args);System.out.println("后置代理");return result;}
}

?

調(diào)用

 CglibProxy proxy = new CglibProxy();//通過(guò)生成子類(lèi)的方式創(chuàng)建代理類(lèi)SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);proxyImp.say();

?

CGLib動(dòng)態(tài)代理原理及實(shí)現(xiàn)

Java動(dòng)態(tài)代理機(jī)制詳解(JDK 和CGLIB,Javassist,ASM)[轉(zhuǎn)]

cglib動(dòng)態(tài)代理介紹(一)

?

五.自己手寫(xiě)代碼實(shí)現(xiàn)Spring的基本功能

需要說(shuō)這個(gè)作者寫(xiě)到這一系列文章非常好【SSH進(jìn)階之路】一步步重構(gòu)容器實(shí)現(xiàn)Spring框架——徹底封裝,實(shí)現(xiàn)簡(jiǎn)單靈活的Spring框架(十一)

代碼:http://download.csdn.net/detail/jiuqiyuliang/8483981

這篇博文的目標(biāo)是不僅形似Spring的IoC,而且要神似Spring的IoC,將對(duì)象的依賴(lài)關(guān)系進(jìn)一步封裝。

完整的項(xiàng)目結(jié)構(gòu)

?

Dao接口和實(shí)現(xiàn)

?

public interface Dao {public void daoMethod();
}
public class Dao4MySqlImpl implements Dao {public void daoMethod(){System.out.println("Dao4MySqlImpl.daoMethod()");}
}
public class Dao4OracleImpl implements Dao {public void daoMethod(){System.out.println("Dao4OracleImpl.daoMethod()");}
}


Service接口和實(shí)現(xiàn)

?

public interface Service {public void serviceMethod();
}
public class ServiceImpl implements Service {private Dao dao;  //依賴(lài)注入public void setDao(Dao dao) {this.dao= dao;}@Overridepublic void serviceMethod() {dao.daoMethod();}
}

?

public interface BeanFactory {Object getBean(String beanName);
}
import java.util.ArrayList;
import java.util.List;public class BeanDefinition {private String id;private String className;private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>();public BeanDefinition(String id, String className) {this.id = id;this.className = className;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public List<PropertyDefinition> getPropertys() {return propertys;}public void setPropertys(List<PropertyDefinition> propertys) {this.propertys = propertys;}
}

?

核心容器

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 容器** @author liang**/
public class ClassPathXmlApplicationContext implements BeanFactory {// 用于存放Beanprivate List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();// 用于存放Bean的實(shí)例private Map<String, Object> sigletons =new HashMap<String, Object>();public ClassPathXmlApplicationContext(String fileName) {this.readXML(fileName);this.instanceBeans();this.injectObject();}/*** 為bean對(duì)象的屬性注入值*/private void injectObject() {for (BeanDefinition beanDefinition :beanDefines) {Object bean = sigletons.get(beanDefinition.getId());if(bean != null){try {// 通過(guò)Introspector取得bean的定義信息,之后再取得屬性的描述信息,返回一個(gè)數(shù)組PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();for(PropertyDefinition propertyDefinition:beanDefinition.getPropertys()){for(PropertyDescriptor properdesc: ps){if(propertyDefinition.getName().equals(properdesc.getName())){// 獲取屬性的setter方法,privateMethod setter = properdesc.getWriteMethod();if(setter != null){Object value = sigletons.get(propertyDefinition.getRef());// 允許訪問(wèn)私有方法setter.setAccessible(true);// 把引用對(duì)象注入到屬性setter.invoke(bean, value);}break;}}}} catch (Exception e) {e.printStackTrace();}}}}/*** 完成bean的實(shí)例化*/private void instanceBeans() {for(BeanDefinition beanDefinition : beanDefines){try {if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance() );}} catch (Exception e) {e.printStackTrace();}}}/*** 讀取xml配置文件*/private void readXML(String fileName) {// 創(chuàng)建SAXBuilder對(duì)象SAXBuilder saxBuilder = new SAXBuilder();try {// 讀取資源,獲得document對(duì)象Document doc = saxBuilder.build(this.getClass().getClassLoader().getResourceAsStream(fileName));// 獲取根元素Element rootEle = doc.getRootElement();// 從根元素獲得所有的子元素,建立元素集合List listBean = XPath.selectNodes(rootEle, "/beans/bean");// 遍歷根元素的子元素集合,掃描配置文件中的beanfor (int i = 0; i < listBean.size(); i++) {// 將根元素beans下的bean子元素作為一個(gè)新的子根元素Element elementBean = (Element) listBean.get(i);//獲取id屬性值String id = elementBean.getAttributeValue("id");//獲取class屬性值String clazz = elementBean.getAttributeValue("class");BeanDefinition beanDefine = new BeanDefinition(id,clazz);// 獲取子根元素bean下的所有property子元素List listProperty = elementBean.getChildren("property");// 遍歷子根元素的子元素集合(即遍歷property元素)for (int j = 0; j < listProperty.size(); j++) {// 獲取property元素Element elmentProperty = (Element)listProperty.get(j);// 獲取name屬性值String propertyName = elmentProperty.getAttributeValue("name");// 獲取ref屬性值String propertyref = elmentProperty.getAttributeValue("ref");PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName,propertyref);beanDefine.getPropertys().add(propertyDefinition);}// 將javabean添加到集合中beanDefines.add(beanDefine);}} catch (Exception e) {e.printStackTrace();}}/*** 獲取bean實(shí)例*/@Overridepublic Object getBean(String beanName) {return this.sigletons.get(beanName);}
}

?

public class PropertyDefinition {private String name;private String ref;public PropertyDefinition(String name, String ref) {this.name = name;this.ref = ref;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getRef() {return ref;}public void setRef(String ref) {this.ref = ref;}}

?

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans><bean id="dao" class="com.tgb.container.dao.impl.Dao4MySqlImpl" /><bean id="service" class="com.tgb.container.service.impl.ServiceImpl"><property name="dao" ref="dao"></property></bean>
</beans>

?

總結(jié)

以上是生活随笔為你收集整理的支撑Java框架的基础技术:泛型,反射,动态代理,cglib的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。