Spring + Hibernate 是黃金組合,但 AppFuse 等示例專案的 XML 配置往往冗長難讀。本系列探索**最適合團隊的 Spring 配置風格**,核心原則:**框架提供極致靈活性,但僅在需要時使用**。
<bean name="customerController" class="..." autowire="byName"/>
<!-- 自動查找名為 customerDAO 的 bean 注入 customerController.customerDAO 屬性 -->
autowire="byName" + 具體屬性顯式 <property> 覆蓋<beans default-autowire="byName"> (Rod Johnson 建議僅開發期使用,生產環境顯式化)<!-- 父 Bean 定義冗長的事務代理模板 -->
<bean id="baseTxService" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
<!-- 子 Bean 僅需指定 target -->
<bean id="customerManager" parent="baseTxService">
<property name="target">
<bean class="org.springside.bookstore.service.CustomerManager"/> <!-- Inner Bean -->
</property>
</bean>
abstract="true" 父 Bean 不實例化,僅作模板target,無需單獨 ID,配合 Controller autowire="byName" 實現「Proxy 冒充 Target 被注入」| 組件 | 傳統冗長版 | 極簡版 |
|---|---|---|
| Controller | 15-20 行 (含 view、validator、dao ref 等) | <bean name="customerController" class="..." autowire="byName"/> |
| DAO | 5-8 行 (sessionFactory ref 等) | <bean id="customerDAO" class="..."/> |
| Service | 20+ 行 (事務屬性、target、proxy 接口等) | 5 行 (繼承 baseTxService + Inner Bean target) |
| 原寫法 | 簡化寫法 | 說明 |
|---|---|---|
<property name="foo"><value>bar</value></property> | <property name="foo" value="bar"/> | 屬性值扁平化 |
<property name="foo"><ref bean="bar"/></property> | <property name="foo" ref="bar"/> | 引用扁平化 |
<list><value>a</value><value>b</value></list> | value="a b" | List 空格分隔 (需無空格值) |
注意:CDATA、複雜嵌套仍需子元素寫法。
<!-- 傳統 -->
<bean id="customerDAO" class="...">
<property name="maxCount" value="10"/>
</bean>
<!-- Spring 2.0+ 自定義 Schema -->
<customerDAO class="..." maxCount="10"/>
<!-- 元素名即 Bean ID,屬性即屬性值,極致語義化 -->
參考 JPetStore 示例,需編寫 XSD + NamespaceHandler + BeanDefinitionParser,適合大型項目構建領域專用配置 DSL。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 編輯器自動提示元素、屬性、驗證拼寫 -->
</beans>
無 Spring IDE 插件時,標準 XSD 仍能提供基本智能感知。
BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator 自動創建代理階段 1:掌握 autowire、父子 Bean、Inner Bean、屬性扁平化 → 即時見效
階段 2:建立項目基礎設施模板 (baseTxService 等) → 團隊標準化
階段 3:Spring 2.0+ Schema 定制 DSL → 領域語言化配置
階段 4:註解驅動 (@Autowired, @Transactional, @Component) → XML 僅保留基礎設施
階段 5:Java Config (@Configuration, @Bean) → 類型安全、重構友好、無 XML
本文聚焦階段 1-2,**在不引入註解/Java Config 風險的前提下,將 XML 壓縮 70% 以上**。下篇將探討註解驅動與 Java Config 實戰。