1、定義接口
package com.service; public interface Service { public void queryDao(); } package com.dao; public interface Dao { public void query(); }
2、實現類
package com.service; import com.dao.Dao; public class ServiceImpl implements Service { Dao dao ; Dao getDao() { return dao; } public void setDao(Dao dao) { this.dao = dao; } public void queryDao() { System.out.println("開始調用Dao!"); dao.query(); } } package com.dao; public class DaoImpl implements Dao { @Override public void query(){ System.out.println("操作數據庫!"); } }
3、工廠類
package com.util; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.File; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class BeanFactory { public Map map = new HashMap<String,Object>(); public BeanFactory(String xml) { parseXml(xml); } public void parseXml(String xml){ try { File file = new File(this.getClass().getResource("/").getPath()+"//"+xml); SAXReader reader = new SAXReader(); Document document = reader.read(file); Element root = document.getRootElement(); for (Iterator<Element> it1 = root.elementIterator(); it1.hasNext();) { Element element = it1.next(); Attribute elementAttrId = element.attribute("id"); String elementId = elementAttrId.getValue(); Attribute elementAttrClass = element.attribute("class"); String elementClass = elementAttrClass.getValue(); //實例化對象 Class clazz = Class.forName(elementClass); Object beanObject = clazz.newInstance(); map.put(elementId,beanObject); for (Iterator<Element> it2 = element.elementIterator(); it2.hasNext();) { Element element2 = it2.next(); if("property".equals(element2.getName())){ String attributeName = element2.attribute("name").getValue(); String attributeRef = element2.attribute("ref").getValue(); //獲取目標對象中的所有屬性,[規則:屬性的名字一定和property中的那麼保持一致] Field field = beanObject.getClass().getDeclaredField(attributeName); //說明依賴已經存在map中,需要將依賴注入到目標中的屬性中 Object injectInObject = map.get(attributeRef); if(map.get(attributeRef)==null){ System.out.println("依賴還沒有注入,請檢查以來是否在"+clazz.getName()+"對象之前已經注入!"); }
//使用反射set方法必須傳的值,否則會報IllegalAccessException:"BeanFactory不能訪問com.service類的成員。ServiceImpl與修飾符" field.setAccessible(true); field.set(beanObject,injectInObject); } } } } catch (Exception e) { e.printStackTrace(); } } public Object getBean(String beanName){ if(map == null || map.get(beanName)==null){ return null; } return map.get(beanName); } }
4、測試類
public static void main(String args[]){ BeanFactory beanFactory = new BeanFactory("spring.xml"); System.out.println(beanFactory.map); Service service = (ServiceImpl)beanFactory.getBean("service"); service.queryDao(); }
使用構造方式依賴注入
package com.util; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class BeanFactory { public Map map = new HashMap<String,Object>(); public BeanFactory(String xml) { parseXml(xml); } public void parseXml(String xml){ try { File file = new File(this.getClass().getResource("/").getPath()+"//"+xml); SAXReader reader = new SAXReader(); Document document = reader.read(file); Element root = document.getRootElement(); for (Iterator<Element> it1 = root.elementIterator(); it1.hasNext();) { Element element = it1.next(); Attribute elementAttrId = element.attribute("id"); String elementId = elementAttrId.getValue(); Attribute elementAttrClass = element.attribute("class"); String elementClass = elementAttrClass.getValue(); //實例化對象 Class clazz = Class.forName(elementClass); Object beanObject = clazz.newInstance(); for (Iterator<Element> it2 = element.elementIterator(); it2.hasNext();) { Element element2 = it2.next(); //實例化對象,如果子標籤是property則默認使用setter方法,並且默認構造 String attributeName = element2.attribute("name").getValue(); String attributeRef = element2.attribute("ref").getValue(); Object injectInObject = null; if("property".equals(element2.getName())){ injectInObject = map.get(attributeRef); //說明依賴不存在map中,需要將依賴注入到目標中的屬性中 if(injectInObject==null){ System.out.println("依賴對象還沒有註冊到容器!"); } //獲取目標對象中的所有屬性,[規則:屬性的名字一定和property中的那麼保持一致] Field field = beanObject.getClass().getDeclaredField(attributeName); field.setAccessible(true); field.set(beanObject,injectInObject); //當然構造方法中可以有多個參數,這裏只默認爲一個注入對象 }else if("constructor-arg".equals(element2.getName())){ injectInObject = map.get(attributeRef); if(injectInObject==null){ System.out.println("依賴對象還沒有註冊到容器!"); } Constructor constructor= clazz.getConstructor(injectInObject.getClass().getInterfaces()[0]); beanObject = constructor.newInstance(injectInObject); }else{ System.out.println("解析中出現特殊子標籤,請繼續編寫!"); } } if(beanObject==null){ beanObject = clazz.newInstance(); } map.put(elementId,beanObject); } } catch (Exception e) { e.printStackTrace(); } } public Object getBean(String beanName){ if(map == null || map.get(beanName)==null){ return null; } return map.get(beanName); } }
模擬自動裝配方式,並且屬性方式>自動裝配,自定義異常
1、自動裝配
byType方式:如果xml中beans標籤中包含自動裝配屬性並且value=byType,我們要循環目標對象的屬性,並且使用屬性查找map(已注入的對象)是否一致(這裏判斷的是接口名字),如果一致使用set方式注入,如果map中出現兩個則需要拋出自定義異常(再容器中找到兩個一樣的注入對象)