傳統開發中,類之間直接 new 依賴對象,形成強耦合。工廠模式雖將創建邏輯抽離,但仍需在代碼中硬編碼類名。Spring IOC(控制反轉/依賴注入)將對象創建、依賴關係配置外部化到 XML,容器啟動時通過反射實例化並注入,徹底解耦。
反射是 Java 動態性的核心,運行時可獲取類信息並操作對象:
Class.forName():獲取 Class 對象clazz.newInstance():實例化對象clazz.getMethod(name, paramTypes):獲取方法method.invoke(obj, args):動態調用方法Introspector.getBeanInfo():獲取屬性描述符// 反射調用示例
Class cls = Class.forName("org.amigo.reflection.ReflectionTest");
Class[] ptypes = { String.class, Hashtable.class };
Method method = cls.getMethod("testMethod", ptypes);
Object[] args = { "hello", new Hashtable<>() };
String result = (String) method.invoke(new ReflectionTest(), args);
核心流程:解析 XML → 反射實例化 Bean → 反射設置屬性 → 緩存至 Map → 提供 getBean() 獲取。
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="javaBean" class="org.amigo.reflection.JavaBean">
<property name="userName"><value>xxxx</value></property>
<property name="password"><value>12345678</value></property>
</bean>
</beans>
public class BeanFactory {
private Map beanMap = new HashMap<>();
public void init(String xml) {
try {
SAXReader reader = new SAXReader();
InputStream ins = Thread.currentThread().getContextClassLoader().getResourceAsStream(xml);
Document doc = reader.read(ins);
Element root = doc.getRootElement();
for (Iterator i = root.elementIterator("bean"); i.hasNext();) {
Element beanEle = (Element) i.next();
String id = beanEle.attributeValue("id");
String className = beanEle.attributeValue("class");
Class beanClass = Class.forName(className);
Object obj = beanClass.newInstance();
BeanInfo info = Introspector.getBeanInfo(beanClass);
PropertyDescriptor[] pds = info.getPropertyDescriptors();
for (Iterator ite = beanEle.elementIterator("property"); ite.hasNext();) {
Element propEle = (Element) ite.next();
String propName = propEle.attributeValue("name");
String value = propEle.elementText("value");
for (PropertyDescriptor pd : pds) {
if (pd.getName().equalsIgnoreCase(propName)) {
Method setter = pd.getWriteMethod();
setter.invoke(obj, value);
break;
}
}
}
beanMap.put(id, obj);
}
} catch (Exception e) { e.printStackTrace(); }
}
public Object getBean(String beanName) { return beanMap.get(beanName); }
}
public static void main(String[] args) {
BeanFactory factory = new BeanFactory();
factory.init("config.xml");
JavaBean bean = (JavaBean) factory.getBean("javaBean");
System.out.println("userName=" + bean.getUserName()); // xxxx
System.out.println("password=" + bean.getPassword()); // 12345678
}
ClassPathXmlApplicationContext("a.xml","b.xml")<property name="dao" ref="userDao"/> 遞歸注入init-method、destroy-method、InitializingBean、DisposableBeanBeanPostProcessor 攔截初始化前後,實現 AOP 代理創建這正是 Spring 容器啟動的核心流程,理解它有助於排查循環依賴、Bean 創建失敗等疑難問題。