在沒有IOC容器的狀況下,若是咱們須要某個類具體的操做以下所示:git
傳統的Bean建立程序員
首先在這裏強調一下IOC不是Spring提出來了,在Spring以前就已經有人提出了IOC思想,只不過在Spring以前都是偏理論化沒有一個具體的落地方案,Spring在技術層面把IOC思想體現的淋漓盡致。github
從上圖可知:面試
在理解控制反轉以前咱們首先要清楚控制是指什麼? 反轉又反轉了什麼?spring
將到IOC確定會有人想到DI(Dependancy Injection)依賴注入,那這二者有什麼不一樣和相同呢?後端
小夥伴們看到這裏其實對IOC容器已經有了必定的瞭解。那若是在面試的過程當中面試官問你如何實現一個自定義的IOC容器。你能夠講出的具體思路嘛? 能夠先想想在繼續往下看,看看是否是和本身的想發不謀而合。bash
思路大體以下所示:微信
<?xml version="1.0" encoding="UTF-8" ?>
<!--跟標籤beans,裏面配置一個又一個的bean子標籤,每個bean子標籤都表明一個類的配置-->
<beans>
<!--id標識對象,class是類的全限定類名-->
<bean id="orderDao" class="com.customize.spring.dao.impl.OrderDaoImpl">
</bean>
<bean id="stockDao" class="com.customize.spring.dao.impl.StockDaoImpl">
</bean>
<bean id="orderService" class="com.customize.spring.service.impl.OrderServiceImpl">
<!--經過set方法注入-->
<property name="setOrderDao" ref="orderDao"></property>
<property name="setStockDao" ref="stockDao"></property>
</bean>
</beans>
複製代碼
public class BeanFactory {
/**
* 存放對象
*/
private static Map<String, Object> map = new ConcurrentHashMap<>();
/**
* 對外提供的接口
* @param id
* @return
*/
public static Object getBean(String id) {
return map.get(id);
}
static {
// 只加載一次就是在BeanFactory初始化的時候去加載類
// 任務一:讀取解析xml,經過反射技術實例化對象而且存儲待用(map集合)
System.out.println("開始加載Bean對象");
// 加載xml
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
// 解析xml
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(resourceAsStream);
Element rootElement = document.getRootElement();
List<Element> beanList = rootElement.selectNodes("//bean");
for (int i = 0; i < beanList.size(); i++) {
Element element = beanList.get(i);
// 處理每一個bean元素,獲取到該元素的id 和 class 屬性
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
// 經過反射技術實例化對象
Class<?> aClass = Class.forName(clazz);
Object o = aClass.newInstance();
// 存儲到map中待用
map.put(id,o);
}
// 實例化完成以後維護對象的依賴關係,檢查哪些對象須要傳值進入,根據它的配置,咱們傳入相應的值
// 有property子元素的bean就有傳值需求
List<Element> propertyList = rootElement.selectNodes("//property");
// 解析property,獲取父元素
for (int i = 0; i < propertyList.size(); i++) {
Element element = propertyList.get(i);
String name = element.attributeValue("name");
String ref = element.attributeValue("ref");
// 找到當前須要被處理依賴關係的bean
Element parent = element.getParent();
// 調用父元素對象的反射功能
String parentId = parent.attributeValue("id");
Object parentObject = map.get(parentId);
// 遍歷父對象中的全部方法,找到"set" + name
Method[] methods = parentObject.getClass().getMethods();
for (int j = 0; j < methods.length; j++) {
Method method = methods[j];
// 該方法就是 setAccountDao(AccountDao accountDao)
if(method.getName().equalsIgnoreCase(name)) {
method.invoke(parentObject,map.get(ref));
}
}
// 把處理以後的parentObject從新放到map中
map.put(parentId,parentObject);
}
System.out.println("加載完畢,Map中的Bean對象個數爲:" + map.size());
} catch (Exception e) {
e.printStackTrace();
}
}
}
複製代碼
public class OrderServiceImpl implements OrderService {
private OrderDao orderDao;
private StockDao stockDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void setStockDao(StockDao stockDao) {
this.stockDao = stockDao;
}
@Override
public void order(Order order) {
// 沒有IOC容器的狀況下
// OrderDao orderDao = new OrderDaoImpl();
// // 保存訂單
// orderDao.save(order);
//
// //扣除庫存
// StockDao stockDao = new StockDaoImpl();
// stockDao.subStock(order.getName());
// 有IOC容器的基礎上
orderDao.save(order);
//扣除庫存
stockDao.subStock(order.getName());
System.out.println("下單成功");
}
}
複製代碼
啓動
ide
測試 學習
有幫忙到你記得點個小星星哦。