1. 程式人生 > >深入理解Spring--動手實現一個簡單的SpringIOC容器

深入理解Spring--動手實現一個簡單的SpringIOC容器

複製程式碼
package com.wang.main;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;

import com.wang.config.Bean;
import com.wang.config.Property;
import com.wang.config.parse.ConfigManager; import com.wang.entity.Student; //import com.wang.utils.BeanUtils; import com.wang.utils.BeanUtil; public class ClassPathXmlApplicationContext implements BeanFactory { // 獲得讀取的配置檔案中的Map資訊 private Map<String, Bean> map; // 作為IOC容器使用,放置sring放置的物件
private Map<String, Object> context = new HashMap<String, Object>(); public ClassPathXmlApplicationContext(String path) { // 1.讀取配置檔案得到需要初始化的Bean資訊 map = ConfigManager.getConfig(path); // 2.遍歷配置,初始化Bean for (Entry<String, Bean> en : map.entrySet()) { String beanName
= en.getKey(); Bean bean = en.getValue(); Object existBean = context.get(beanName); // 當容器中為空並且bean的scope屬性為singleton時 if (existBean == null && bean.getScope().equals("singleton")) { // 根據字串建立Bean物件 Object beanObj = createBean(bean); // 把建立好的bean物件放置到map中去 context.put(beanName, beanObj); } } } // 通過反射建立物件 private Object createBean(Bean bean) { // 建立該類物件 Class clazz = null; try { clazz = Class.forName(bean.getClassName()); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new RuntimeException("沒有找到該類" + bean.getClassName()); } Object beanObj = null; try { beanObj = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("沒有提供無參構造器"); } // 獲得bean的屬性,將其注入 if (bean.getProperties() != null) { for (Property prop : bean.getProperties()) { // 注入分兩種情況 // 獲得要注入的屬性名稱 String name = prop.getName(); String value = prop.getValue(); String ref = prop.getRef(); // 使用BeanUtils工具類完成屬性注入,可以自動完成型別轉換 // 如果value不為null,說明有 if (value != null) { Map<String, String[]> parmMap = new HashMap<String, String[]>(); parmMap.put(name, new String[] { value }); try { BeanUtils.populate(beanObj, parmMap); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("請檢查你的" + name + "屬性"); } } if (ref != null) { // 根據屬性名獲得一個注入屬性對應的set方法 // Method setMethod = BeanUtil.getWriteMethod(beanObj, // name); // 看一看當前IOC容器中是否已存在該bean,有的話直接設定沒有的話使用遞迴,建立該bean物件 Object existBean = context.get(prop.getRef()); if (existBean == null) { // 遞迴的建立一個bean existBean = createBean(map.get(prop.getRef())); // 放置到context容器中 // 只有當scope="singleton"時才往容器中放 if (map.get(prop.getRef()).getScope() .equals("singleton")) { context.put(prop.getRef(), existBean); } } try { // setMethod.invoke(beanObj, existBean);
              //通過BeanUtils為beanObj設定屬性
BeanUtils.setProperty(beanObj, name, existBean); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("您的bean的屬性" + name + "沒有對應的set方法"); } } } } return beanObj; } @Override public Object getBean(String name) { Object bean = context.get(name); // 如果為空說明scope不是singleton,那麼容器中是沒有的,這裡現場建立 if (bean == null) { bean = createBean(map.get(name)); } return bean; } }
複製程式碼