![](/img/trans.png)
[英]Injecting concrete class in Spring that needs to subclass a framework type
[英]Spring is injecting concrete class instead of proxy
我有一個問題,Spring將DAO對象的代理注入到服務中,但是這個服務被注入到控制器中它是具體的類。 這不允許我使用服務范圍的事務並分別為每個DAO調用啟動事務。 這是我期望的行為。
組態:
Controller是帶有@Controller注釋和構造函數DI的類。
服務:
@Component @Transactional public class UserServiceImpl implements UserService { ...}
道:
@Component @Transactional public class UserDaoImpl implements UserDao {
JPA配置:
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="xxxPersistenceUnit"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven />
任何人都知道為什么會這樣?
很可能你的UserServiceImpl
是在servlet上下文中錯誤地創建的 - 請檢查context:component-scan
表達式以檢查那里只包含Controller
類。
有關組件掃描過濾器的示例,請參閱@Service 。
例如,如果在根Web應用程序上下文中聲明了事務管理器bean和<tx:annotation-driven>
,那么將僅為根應用程序上下文中的bean創建事務代理(來自Spring文檔 ):
BeanPostProcessor接口的范圍是每個容器。 這僅在您使用容器層次結構時才有意義。 如果在一個容器中定義BeanPostProcessor,它將只對該容器中的bean執行操作。 在一個容器中定義的Bean不會被另一個容器中的BeanPostProcessor進行后處理,即使兩個容器都是同一層次結構的一部分。
不太可能的是,用戶服務的事務配置被配置為使用另一個事務管理器(或另一個默認傳播),但在這種情況下, TransactionInterceptor
調用將出現在DAO方法的堆棧跟蹤中。
如果你明白自己在做什么,那么在Spring中的DAO類上使用@Transactional
是絕對可以的 - 存儲庫或DAO無法打開事務的想法來自於你必須創建一個樣板代碼來打開事務的黑暗時期。難以管理事務實例(並且您無法確定如何管理事務)。 但是當你使用聲明性配置時,事情並沒有那么糟糕。 Spring提升了配置約定的風格,大多數方法都使用Propagation.REQUIRED
事務模式。 在Spring Propagation.REQUIRED
是使用@Transactional
裝飾方法時的默認模式(此傳播被硬編碼為@Transactional
注釋聲明),這意味着新的邏輯事務被映射到同一個物理事務,因此使用@Transactional
裝飾DAO類@Transactional
是無害的。
有關Spring中事務傳播的參考,請參見http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html#tx-propagation
在Spring Data JPA中(我很確定他們知道他們在做什么),例如, 默認情況下,存儲庫實例上的CRUD方法是事務性的 。 在某些情況下,這可能很有用,機制與Hibernate允許你從Session
獲取()一些任意對象進行顯示而不聲明顯式事務(當然這並不意味着框架以某種方式設法在沒有事務的情況下進行)相同 - 這種情況隱含在這種情況下)。
我在理解您所說的內容時遇到了一些麻煩,但您似乎對每次DAO呼叫都獲得新事務感到驚訝,而不僅僅是在服務呼叫上。 不幸的是,這正是你通過在DAO類上放置“@Transactional”而指定的。 你的DAO不應該是交易性的,至少如果你遵循通常的模式。 如果我理解正確,您應該刪除DAO類上的@Transactional注釋。
其他響應者是正確的,因為你不應該將你的DAO注釋為@Transactional
,但要真正理解發生了什么,你應該參考Spring Reference Manual中的Transaction Propagation部分 。 使用@Transactional
時的默認傳播是REQUIRES_PROPAGATION
,因此請具體查看。
你的問題不是那么具體,所以我不確定你到底在想什么。
編輯:重新閱讀您的問題時,組件掃描可能存在問題。 檢查以確保<tx:annotation-driven />
與組件掃描服務類的應用程序上下文相同。
您不應該在DAO對象中使用“@Transactional”注釋。 您正在服務中定義它,並且授予您在服務方法內部調用的所有DAO方法在同一事務中執行,當您說“服務范圍事務”時,這似乎正是您想要的?
另外,如建議的那樣,您可能希望在UserServiceImpl中將注釋從“@Component”更改為“@Service”,並在UserDaoImpl中將注釋更改為“@Repository”。
最好的祝福。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.