項目中每個 DAO 類都需注入 HibernateTemplate,導致大量重複配置:
<bean id="userDao" class="com.dao.UserDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"/>
</bean>
<bean id="orderDao" class="com.dao.OrderDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"/>
</bean>
... 大量重複 ...
實現一個後置處理器,掃描所有 DAO Bean,自動注入 HibernateTemplate,無需 XML 逐個配置。
public class HibernateTemplateInjector implements BeanPostProcessor {
@Autowired
private HibernateTemplate hibernateTemplate;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 約定:所有 DAO 實現類名以 "DaoImpl" 結尾,或實現 BaseDao 接口
if (beanName.endsWith("DaoImpl") || bean instanceof BaseDao) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "hibernateTemplate");
if (field != null) {
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, bean, hibernateTemplate);
}
} catch (Exception e) {
throw new BeanInitializationException("注入 HibernateTemplate 失敗: " + beanName, e);
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
<!-- 僅需註冊一次 -->
<bean class="com.config.HibernateTemplateInjector"/>
<!-- 所有 DAO 只需聲明字段,無需 setter/配置 -->
<bean id="userDao" class="com.dao.UserDaoImpl"/> <!-- 自動注入 -->
<bean id="orderDao" class="com.dao.OrderDaoImpl"/>
定義 @AutoHibernateTemplate 註解標記需注入的字段,避免誤注入:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoHibernateTemplate {}
// DAO 中
@AutoHibernateTemplate
private HibernateTemplate hibernateTemplate;
// 處理器中判斷
if (field.isAnnotationPresent(AutoHibernateTemplate.class)) { ... }
| 維度 | 傳統 XML 逐個注入 | BeanPostProcessor 自動注入 |
|---|---|---|
| 配置量 | O(N) 隨 DAO 增長 | O(1) 固定 |
| 維護性 | 新增 DAO 必改 XML | 零配置,約定優於配置 |
| 靈活性 | 低 | 可結合註解/命名規則精準控制 |
完整示例可參考:Spring HibernateTemplate 自動注入實戰
採用此模式,DAO 層代碼更乾淨,擴展新 DAO 只需編寫業務邏輯,基礎設施自動裝配。