IOC (Inversion of Control) 核心是**依賴注入 (DI)**:將物件建立與依賴關係交由容器管理。Spring 利用 **Java 反射** 實現 XML 配置到物件圖的構建。
public class JavaBean {
private String username, password;
// getter/setter 省略
}
// 單一屬性反射注入
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()));
}
}
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>
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());
}
}
bean 元素的 id、class、property 列表。Class.forName() 載入類別,newInstance() 建立實例。Introspector 獲取屬性描述符 (PropertyDescriptor) 對應 setter。property,型別轉換後透過 Method.invoke() 調用 setter 注入值。Map<id, bean>,供 getBean() 取用。