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

Spring XML 配置全解析:從入門到最佳實踐

     編輯:Java 相關知識

前言

雖然 Spring Boot 推廣了基於註解和 Java Config 的配置方式,但在大量存量項目、傳統企業級應用中,XML 配置依然佔據重要地位。本文系統梳理 Spring XML 配置的核心機制、命名空間體系、常見場景與最佳實踐。

一、XML 配置核心架構

1. 文件結構與根元素

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="https://www.springframework.org/schema/context"
       xmlns:tx="https://www.springframework.org/schema/tx"
       xsi:schemaLocation="
           https://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           https://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd
           https://www.springframework.org/schema/tx
           https://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- Bean 定義與配置 -->

</beans>

核心屬性解析:

  • id:Bean 唯一標識符(XML ID 類型約束,不可包含特殊字符)
  • name:別名支援,可包含逗號/分號/空格分隔的多個名稱
  • class:全限定類名
  • scope:作用域(singleton/prototype/request/session/application)
  • lazy-init:延遲初始化(僅 singleton 有效)
  • init-method / destroy-method:生命週期回調
  • factory-bean / factory-method:工廠模式創建實例

2. 依賴注入三種方式

構造器注入

<bean id="userService" class="com.example.service.UserServiceImpl">
    <constructor-arg index="0" ref="userDao"/>
    <constructor-arg index="1" value="defaultValue"/>
    <constructor-arg type="java.lang.String" value="config"/>
</bean>

Setter 注入(推薦)

<bean id="userService" class="com.example.service.UserServiceImpl">
    <property name="userDao" ref="userDao"/>
    <property name="maxRetry" value="3"/>
    <property name="configMap">
        <map>
            <entry key="timeout" value="5000"/>
            <entry key="retry" value="true"/>
        </map>
    </property>
    <property name="serverList">
        <list>
            <value>server1</value>
            <value>server2</value>
        </list>
    </property>
</bean>

p/n 命名空間簡化配置

<beans xmlns:p="https://www.springframework.org/schema/p"
       xmlns:c="https://www.springframework.org/schema/c">

    <!-- p:property (Setter) -->
    <bean id="userService" class="com.example.service.UserServiceImpl"
          p:userDao-ref="userDao" p:maxRetry="3"/>

    <!-- c:constructor-arg (構造器) -->
    <bean id="orderService" class="com.example.service.OrderServiceImpl"
          c:orderDao-ref="orderDao" c:timeout="3000"/>

</beans>

二、核心命名空間深度解析

命名空間前綴核心功能典型標籤
beans默認Bean 定義基礎<bean>, <alias>, <import>
contextcontext:掃描、屬性占位、注解驅動<component-scan>, <property-placeholder>, <annotation-config>
aopaop:切面編程配置<config>, <aspect>, <pointcut>, <advisor>
txtx:聲明式事務管理<annotation-driven>, <advice>, <attributes>
jdbcjdbc:數據源、模板初始化<initialize-database>, <embedded-database>
mvcmvc:Spring MVC 基礎設施<annotation-driven>, <interceptors>, <view-resolvers>
tasktask:排程與異步執行<annotation-driven>, <executor>, <scheduler>
jmsjms:消息佇列整合<listener-container>, <jca-listener-container>
cachecache:緩存抽象<annotation-driven>, <advice>

1. context 命名空間實戰

<!-- 1. 組件掃描:排除 Controller,只掃描 Service/Repository -->
<context:component-scan base-package="com.example">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!-- 2. 屬性文件占位符 -->
<context:property-placeholder location="classpath:jdbc.properties,classpath:redis.properties"
                              ignore-unresolvable="true"/>

<!-- 3. 啟用 @Autowired/@Resource/@PostConstruct 等注解處理 -->
<context:annotation-config/>

<!-- 4. 載入時編織 (LTW) -->
<context:load-time-weaver aspectj-weaving="on"/>

2. tx 事務管理配置

<!-- 數據源與事務管理器 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!-- 聲明式事務:注解驅動 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

<!-- 或 XML 配置式事務(細粒度控制) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
        <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
        <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service..*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>

3. mvc 命名空間配置

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                    <property name="dateFormat">
                        <bean class="java.text.SimpleDateFormat" c:_0="yyyy-MM-dd HH:mm:ss"/>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

<!-- 靜態資源處理 -->
<mvc:resources mapping="/static/**" location="/static/,classpath:/META-INF/resources/webjars/"/>
<mvc:resources mapping="/favicon.ico" location="/favicon.ico"/>

<!-- 視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
    <property name="exposeContextBeansAsAttributes" value="true"/>
</bean>

<!-- 攔截器配置 -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/api/**"/>
        <mvc:exclude-mapping path="/api/login"/>
        <bean class="com.example.interceptor.AuthInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

三、Web.xml 與 Spring 容器啟動

1. ContextLoaderListener(根容器)

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext-*.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

載入:Service、DAO、DataSource、TransactionManager 等業務層 Bean

2. DispatcherServlet(Web 容器)

<servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

<servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

載入:Controller、ViewResolver、Interceptor、HandlerMapping 等 Web 層 Bean

3. 父子容器關係

  • 根容器(ContextLoaderListener)為父容器
  • DispatcherServlet 容器為子容器
  • 子容器可訪問父容器 Bean,父容器不可訪問子容器 Bean
  • 建議:業務層放父容器,Web 層放子容器

四、高級配置技巧

1. Profile 環境隔離

<beans profile="dev">
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="url" value="jdbc:mysql://localhost:3306/dev_db"/>
    </bean>
</beans>

<beans profile="prod">
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="jdbcUrl" value="${prod.jdbc.url}"/>
    </bean>
</beans>

<!-- web.xml 啟動指定 profile -->
<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>prod</param-value>
</context-param>

2. SpEL 表達式注入

<bean id="appConfig" class="com.example.config.AppConfig">
    <property name="appName" value="#{systemProperties['app.name'] ?: 'DefaultApp'}"/>
    <property name="serverPort" value="#{ @serverConfig.port + 100 }"/>
    <property name="activeProfiles" value="#{ @environment.activeProfiles }"/>
    <property name="timeout" value="#{ T(java.lang.Math).random() * 1000 }"/>
</bean>

3. FactoryBean 自定義創建邏輯

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mapperLocations" value="classpath:mappers/*.xml"/>
    <property name="typeAliasesPackage" value="com.example.domain"/>
</bean>

<!-- 暴露 FactoryBean 本身而非產出對象 -->
<bean id="&sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" />

4. 導入與模塊化配置

<!-- 1. 導入單個文件 -->
<import resource="classpath:datasource.xml"/>

<!-- 2. 通配符批量導入 -->
<import resource="classpath*:config/*-context.xml"/>

<!-- 3. 條件導入 (Spring 4.3+) -->
<beans profile="!test">
    <import resource="classpath:production-beans.xml"/>
</beans>

五、常見問題與最佳實踐

問題現象根因分析解決方案
循環依賴A 構造器注入 B,B Setter 注入 A改用 Setter 注入、@Lazy、或重構設計
Bean 重複定義多文件定義同 id、掃描與 XML 衝突統一命名規範、使用 allow-bean-definition-overriding="false"
屬性占位符無法解析PropertyPlaceholderConfigurer 未加載、路徑錯誤檢查 context:property-placeholder 配置、文件編碼
事務不生效調用內部方法、非 public 方法、異常吞噬確保 public 方法、正確 rollback-for、避免 try-catch 吞異常
靜態資源 404DispatcherServlet 攔截所有請求配置 <mvc:resources/> 或 <mvc:default-servlet-handler/>

最佳實踐清單

  1. 模塊化拆分:datasource.xml, transaction.xml, mvc.xml, business.xml
  2. 命名規範:id 使用 camelCase,業務 Bean 加前綴(userService, orderDao)
  3. 外置配置:所有環境相關參數放入 .properties 文件
  4. 避免硬編碼:類名、SQL、URL 全部外部化
  5. 註釋關鍵配置:事務屬性、線程池參數、連接池設置必須註釋業務含義
  6. 版本控制:XML Schema 版本號顯式聲明,避免 Spring 版本升級導致解析失敗

六、從 XML 遷移到 Java Config

對應關係對照表

混合配置策略

@Configuration
@ImportResource("classpath:legacy-datasource.xml") // 導入舊 XML
@ComponentScan("com.example.newmodule")             // 掃描新模塊
@EnableTransactionManagement
public class HybridConfig {
    @Bean
    @Profile("cloud")
    public DataSource cloudDataSource() { ... }
}

總結

Spring XML 配置雖然顯得「笨重」,但其聲明式、集中化、環境隔離的特性在大型傳統項目中仍具不可替代優勢。掌握命名空間體系、依賴注入細節、父子容器機制、Profile 隔離等核心知識,是維護和優化存量系統的必備技能。新項目建議優先採用 Spring Boot + Java Config,但理解 XML 原理有助於深度排查框架底層問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
XML 配置Java Config 等價
<bean id="x" class="X">@Bean(name="x") public X x() { return new X(); }
<property name="y" ref="y"/>@Autowired private Y y; 或 @Bean public X x(Y y) { return new X(y); }
<context:component-scan/>@ComponentScan("com.example")
<tx:annotation-driven/>@EnableTransactionManagement
<mvc:annotation-driven/>@EnableWebMvc
<import resource="..."/>@Import({ConfigA.class, ConfigB.class})
<beans profile="dev">@Profile("dev")