首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring IOC 依賴注入原理深度解析:反射機制、XML 解析、BeanFactory 手寫實現

     編輯:Java 綜合教學

Spring IOC 依賴注入原理深度解析

IOC (Inversion of Control) 核心是**依賴注入 (DI)**:將物件建立與依賴關係交由容器管理。Spring 利用 **Java 反射** 實現 XML 配置到物件圖的構建。

1. 簡單 Bean 定義

public class JavaBean {
    private String username, password;
    // getter/setter 省略
}

2. 反射手動注入

// 單一屬性反射注入
Class c = Class.forName("spring_IOC.JavaBean");
Method m = c.getMethod("setUsername", String.class);
JavaBean bean = new JavaBean();
m.invoke(bean, "hello world"); // 呼叫 setter

// 批次屬性注入 (模擬 XML 解析結果 Map)
Map<String, Object> props = new HashMap<>();
props.put("username", "tomLuo"); props.put("password", "954");
BeanInfo info = Introspector.getBeanInfo(JavaBean.class);
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
    if (props.containsKey(pd.getName())) {
        pd.getWriteMethod().invoke(bean, props.get(pd.getName()));
    }
}

3. XML 配置檔 config.xml

<?xml version="1.0" encoding="utf-8"?>
<beans>
    <bean id="javaBean" class="spring_IOC.JavaBean">
        <property name="username" value="tom" />
        <property name="password" value="123" />
    </bean>
</beans>

4. 手寫 BeanFactory 完整實現

public class BeanFactory {
    private Map<String, Object> beanMap = new HashMap<>();

    public void init(String xmlPath) throws Exception {
        SAXReader reader = new SAXReader();
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(xmlPath);
        Document doc = reader.read(is);
        Element root = doc.getRootElement();

        for (Iterator it = root.elementIterator("bean"); it.hasNext(); ) {
            Element beanEle = (Element) it.next();
            String id = beanEle.attributeValue("id");
            String className = beanEle.attributeValue("class");

            Class clazz = Class.forName(className);
            Object obj = clazz.newInstance();

            BeanInfo info = Introspector.getBeanInfo(clazz);
            PropertyDescriptor[] pds = info.getPropertyDescriptors();

            for (Iterator pit = beanEle.elementIterator("property"); pit.hasNext(); ) {
                Element propEle = (Element) pit.next();
                String name = propEle.attributeValue("name");
                String value = propEle.attributeValue("value");

                for (PropertyDescriptor pd : pds) {
                    if (pd.getName().equals(name)) {
                        Method setter = pd.getWriteMethod();
                        // 簡單型別轉換 (實際需更完善的 ConversionService)
                        Object converted = convert(value, setter.getParameterTypes()[0]);
                        setter.invoke(obj, converted);
                        break;
                    }
                }
            }
            beanMap.put(id, obj);
        }
    }

    public Object getBean(String name) { return beanMap.get(name); }

    // 型別轉換輔助
    private Object convert(String value, Class targetType) {
        if (targetType == int.class || targetType == Integer.class) return Integer.valueOf(value);
        if (targetType == long.class || targetType == Long.class) return Long.valueOf(value);
        if (targetType == boolean.class || targetType == Boolean.class) return Boolean.valueOf(value);
        // ... 其他型別
        return value; // String
    }

    public static void main(String[] args) throws Exception {
        BeanFactory factory = new BeanFactory();
        factory.init("config.xml");
        JavaBean bean = (JavaBean) factory.getBean("javaBean");
        System.out.println("username=" + bean.getUsername());
        System.out.println("password=" + bean.getPassword());
    }
}

核心流程總結

  1. 解析 XML → 獲取 bean 元素的 id、class、property 列表。
  2. 反射 Class.forName() 載入類別,newInstance() 建立實例。
  3. Introspector 獲取屬性描述符 (PropertyDescriptor) 對應 setter。
  4. 遍歷 property,型別轉換後透過 Method.invoke() 調用 setter 注入值。
  5. 將實例存入 Map<id, bean>,供 getBean() 取用。

源碼參考

GitHub 完整範例

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved