理解 Spring IOC 最佳途徑是親手寫一個精簡版容器。本文實現核心流程:BeanFactory 介面定義、AbstractBeanFactory 模板方法、SourceReader 介面與 XMLSourceReader 具體實現(採用 Dom4j 解析 XML)、BeanInfo 承載 Bean 定義元資料、反射實例化與屬性注入、XMLContext 整合啟動。完整代碼可直接運行驗證。
BeanFactory (介面)
↑
AbstractBeanFactory (抽象模板:getBean、parseBean、registerBeans)
↑
XMLContext (具體上下文:指定 XMLSourceReader)
↑
XMLSourceReader (實現 SourceReader,Dom4j 解析 XML → Map<String, BeanInfo>)
↑
BeanInfo (id、type、properties Map)
public interface BeanFactory {
Object getBean(String name);
}
public abstract class AbstractBeanFactory implements BeanFactory {
private Map<String, BeanInfo> container;
protected SourceReader reader;
public AbstractBeanFactory(String filePath) { this.filePath = filePath; }
protected abstract void setReader(SourceReader reader);
public void registerBeans() {
this.container = reader.loadBeans(filePath);
}
@Override
public Object getBean(String name) {
BeanInfo info = container.get(name);
return info == null ? null : parseBean(info);
}
// 反射實例化 + 屬性注入
protected Object parseBean(BeanInfo info) {
Class<?> clazz = Class.forName(info.getType());
Object bean = clazz.newInstance();
for (Map.Entry<String, Object> e : info.getProperties().entrySet()) {
String setter = "set" + Character.toUpperCase(e.getKey().charAt(0)) + e.getKey().substring(1);
Arrays.stream(clazz.getDeclaredMethods())
.filter(m -> m.getName().equals(setter))
.findFirst()
.ifPresent(m -> m.invoke(bean, e.getValue()));
}
return bean;
}
}
public class XMLSourceReader implements SourceReader {
@Override
public Map<String, BeanInfo> loadBeans(String filePath) {
SAXReader reader = new SAXReader();
InputStream ins = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
Document doc = reader.read(ins);
Element root = doc.getRootElement();
Map<String, BeanInfo> map = new HashMap<>();
for (Iterator i = root.elementIterator("bean"); i.hasNext(); ) {
Element ele = (Element) i.next();
String id = ele.attributeValue("id");
String cls = ele.attributeValue("class");
BeanInfo info = new BeanInfo();
info.setId(id); info.setType(cls);
// 解析 yyy
for (Iterator it = ele.elementIterator("property"); it.hasNext(); ) {
Element prop = (Element) it.next();
String name = prop.attributeValue("name");
String value = prop.elementText("value");
info.addProperty(name, value);
}
map.put(id, info);
}
return map;
}
}
public class XMLContext extends AbstractBeanFactory {
public XMLContext(String filePath) {
super(filePath);
setReader(new XMLSourceReader());
registerBeans();
}
@Override protected void setReader(SourceReader r) { this.reader = r; }
}
<beans>
<bean id="person" class="ioc.bean.Person">
<property name="username"><value>zzf</value></property>
<property name="password"><value>12345678</value></property>
</bean>
</beans>
public class Test {
public static void main(String[] args) {
BeanFactory factory = new XMLContext("configuration/config.xml");
Person p = (Person) factory.getBean("person");
System.out.println(p.getUsername()); // zzf
System.out.println(p.getPassword()); // 12345678
}
}

constructor-arg 建構子注入。BeanPostProcessor、InitializingBean 生命週期回調。FactoryBean、@Autowired 註解掃描。通過 6 個核心類、不足 200 行代碼,實現了「XML 配置 → 解析 → 反射實例化 → 屬性注入 → 容器獲取」的完整 IOC 閉環。這正是 Spring IOC 最精華的骨架,理解它能助你在排查 Bean 創建失敗、屬性未注入、循環依賴等問題時直擊本質。