Spring 提倡「面向介面編程」,但實際專案中許多 Service 類(如 SaleOrderManager / SaleOrderManagerImpl)極少有第二種實現。強行抽取介面反而增加維護成本,類似 C++ 的 .h/.cpp 分離卻無多態需求。
Spring 宣告式事務(@Transactional 或 XML `
<bean id="baseService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="proxyTargetClass">
<value>true</value> <!-- 關鍵:強制使用 CGLIB -->
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- 具體 Service 繼承父 Bean,無需實現介面 -->
<bean id="saleOrderManager" parent="baseService">
<property name="target">
<bean class="com.example.service.SaleOrderManager">
<property name="dao" ref="saleOrderDao"/>
</bean>
</property>
</bean>
@EnableTransactionManagement + @Transactional 方式@Configuration
@EnableTransactionManagement(proxyTargetClass = true) // Java Config 強制 CGLIB
public class TxConfig { ... }
@Service // 直接標註在具體類上,無介面
@Transactional
public class SaleOrderManager {
@Autowired private SaleOrderDao dao;
public void saveOrder(Order o) { dao.save(o); }
}
Service Bean 皆為單例,CGLIB 生成子類僅在容器啟動時一次,運行期方法攔截開銷極低(FastClass 機制),不構成效能瓶頸。反而減少介面檔案、簡化導航,提升開發體驗。
final、private、static 方法不受事務管理。@Autowired 構造器(Spring 4.3+ 自動識別)。Serializable 需目標類也實現,且注意 serialVersionUID。合理使用 proxyTargetClass=true,可在不犧牲 Spring AOP 功能(事務、安全、快取)前提下,大幅減少樣板式介面,讓 Service 層回歸「簡單類」本質。這是務實 Spring 開發的重要技巧之一。