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

Spring IOC 核心原理:基於反射機制的依賴注入實現

     編輯:Java 綜合教學

背景:從強耦合到控制反轉

傳統開發中,類之間直接 new 依賴對象,形成強耦合。工廠模式雖將創建邏輯抽離,但仍需在代碼中硬編碼類名。Spring IOC(控制反轉/依賴注入)將對象創建、依賴關係配置外部化到 XML,容器啟動時通過反射實例化並注入,徹底解耦。

Java 反射機制速覽

反射是 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);

手寫簡易 BeanFactory

核心流程:解析 XML → 反射實例化 Bean → 反射設置屬性 → 緩存至 Map → 提供 getBean() 獲取。

配置文件 config.xml

<?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>

BeanFactory 實現

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
}

Spring IOC 進階特性

  • 多配置文件:ClassPathXmlApplicationContext("a.xml","b.xml")
  • Bean 引用:<property name="dao" ref="userDao"/> 遞歸注入
  • 生命周期回調:init-method、destroy-method、InitializingBean、DisposableBean
  • 作用域:singleton、prototype、request、session
  • 後置處理器:BeanPostProcessor 攔截初始化前後,實現 AOP 代理創建

核心原理總結

  1. 讀取配置元數據
  2. 反射實例化 Bean
  3. 反射/內省注入依賴
  4. 管理 Bean 生命周期
  5. 提供統一獲取入口

這正是 Spring 容器啟動的核心流程,理解它有助於排查循環依賴、Bean 創建失敗等疑難問題。

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