支撑Spring的基础技术:泛型,反射,动态代理,cglib等
1.靜態(tài)代碼塊和非靜態(tài)代碼塊以及構(gòu)造函數(shù)
出自尚學(xué)堂視頻:《JVM核心機(jī)制 類加載全過程 JVM內(nèi)存分析 反射機(jī)制核心原理 常量池理解》
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");}
}
?
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)用測試
?
?
public class StaticCodeBlockOrderTest {public static void main(String[] args) {new Child();}
}
?
對象的初始化順序:
首先執(zhí)行父類靜態(tài)的內(nèi)容,父類靜態(tài)的內(nèi)容執(zhí)行完畢后,接著去執(zhí)行子類的靜態(tài)的內(nèi)容,當(dāng)子類的靜態(tài)內(nèi)容執(zhí)行完畢之后,再去看父類有沒有非靜態(tài)代碼塊,
如果有就執(zhí)行父類的非靜態(tài)代碼塊,父類的非靜態(tài)代碼塊執(zhí)行完畢,接著執(zhí)行父類的構(gòu)造方法;父類的構(gòu)造方法執(zhí)行完畢之后,它接著去看子類有沒有非靜態(tài)代碼塊,如果有就執(zhí)行子類的非靜態(tài)代碼塊。
子類的非靜態(tài)代碼塊執(zhí)行完畢再去執(zhí)行子類的構(gòu)造方法。
參考:java中靜態(tài)代碼塊的用法 static用法詳解
?
靜態(tài)代碼塊的應(yīng)用
需要一個(gè)Util類,需要系統(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》
泛型方法
static 后的<E>是泛型聲明,這樣才可以在這個(gè)方法參數(shù)和方法體用泛型
static <E>后的Set<E>是返回值
泛型類:?
不用泛型需要強(qiáng)轉(zhuǎn):?
2.泛型 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è)就明白了
在其他類中例如這個(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è)就會報(bào)錯(cuò)
名稱沖突: getData(Box<Integer>)和getData(Box<String>)具有相同疑符
?
使用通配符?就可以解決這個(gè)問題
?
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é)
?
再來看看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();會報(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í)例
說明還沒有class loader
((Box)o).getT();就已經(jīng)實(shí)例化了。
?
3.Object類型
定義的所有類默認(rèn)都是子類,所有的類都是以標(biāo)準(zhǔn)類Object為基礎(chǔ),Object類型的變量可以存儲指向任意類類型對象的索引。
當(dāng)要為一個(gè)方法來處理未知類型的對象時(shí),這很有用。
?
//存儲的地方HashMap<String , Object> map = new HashMap<String , Object>();User u1=new User();u1.setId(1);u1.setName("ww1");//Object可以塞任意類型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();}
?
?
?
?
4.類名.class, class.forName(), getClass()區(qū)別
1:Class cl=A.class; ?
JVM將使用類A的類裝載器, 將類A裝入內(nèi)存(前提是:類A還沒有裝入內(nèi)存),不對類A做類的初始化工作.返回類A的Class的對象。
2:Class cl=對象引用o.getClass();
返回引用o運(yùn)行時(shí)真正所指的對象(因?yàn)?子對象的引用可能會賦給父對象的引用變量中)所屬的類的Class的對象 。
3:Class.forName("類名");
.裝入類A,并做類的初始化
.getClass()是動(dòng)態(tài)的,其余是靜態(tài)的。
.class和class.forName()只能返回類內(nèi)field的默認(rèn)值,getClass可以返回當(dāng)前對象中field的最新值
Class.forName() 返回的是一個(gè)類,.newInstance() 后才創(chuàng)建一個(gè)對象,Class.forName()的作用是要求JVM查找并加載指定的類,也就是說JVM會執(zhí)行該類的。
?
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將使用類A的類裝載器,將類A裝入內(nèi)存(前提是:類A還沒有裝入內(nèi)存),不對類A做類的初始化工作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í)例化對象,因?yàn)檫@一句才會輸出“靜態(tài)初始化”以及“初始化”O(jiān)bject obj3 = classtype3.newInstance();// 通過實(shí)例化后的對象調(diào)用方法getMethod3.invoke(obj3); // 獲取默認(rèn)值setMethod3.invoke(obj3, "Setting new ", 3); // 設(shè)置getMethod3.invoke(obj3); // 獲取最新System.out.println("----------------");// 返回運(yùn)行時(shí)真正所指的對象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("----------------");// 裝入類,并做類的初始化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í)例化對象Object obj2 = classtype2.newInstance();// 通過實(shí)例化后的對象調(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/
?
5.動(dòng)態(tài)代理和cglib
?
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)建子類的類enhancer.setSuperclass(clazz);enhancer.setCallback(this);//通過字節(jié)碼技術(shù)動(dòng)態(tài)創(chuàng)建子類實(shí)例return enhancer.create();}//實(shí)現(xiàn)MethodInterceptor接口方法public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("前置代理");//通過代理類調(diào)用父類中的方法Object result = proxy.invokeSuper(obj, args);System.out.println("后置代理");return result;}
}
?
?
調(diào)用
?
CglibProxy proxy = new CglibProxy();//通過生成子類的方式創(chuàng)建代理類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)代理介紹(一)
?
?
6.模仿Spring實(shí)現(xiàn)
需要說這個(gè)作者寫到這一系列文章非常好【SSH進(jìn)階之路】一步步重構(gòu)容器實(shí)現(xiàn)Spring框架——徹底封裝,實(shí)現(xiàn)簡單靈活的Spring框架(十一)
代碼:http://download.csdn.net/detail/jiuqiyuliang/8483981
?這篇博文的目標(biāo)是不僅形似Spring的IoC,而且要神似Spring的IoC,將對象的依賴關(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; //依賴注入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對象的屬性注入值*/private void injectObject() {for (BeanDefinition beanDefinition :beanDefines) {Object bean = sigletons.get(beanDefinition.getId());if(bean != null){try {// 通過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());// 允許訪問私有方法setter.setAccessible(true);// 把引用對象注入到屬性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對象SAXBuilder saxBuilder = new SAXBuilder();try {// 讀取資源,獲得document對象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>
7.Smart Framework
?
Smart Framework:輕量級 Java Web 框架
Smart Framework是一個(gè)完整的類似Spring但是更輕量級的項(xiàng)目,學(xué)習(xí)框架的最佳材料之一。
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的支撑Spring的基础技术:泛型,反射,动态代理,cglib等的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell语法以及监控进程不存在重启
- 下一篇: Netbeans使用maven下载源码