我正在学习Spring Core认证,我发现一些与Spring处理事务有关的疑问。
所以我做了一个练习,我找到了类似的东西。
在名为 rewards.internal.RewardNetworkImpl 的班级中,我有这样的方法:
@Transactional
public RewardConfirmation rewardAccountFor(Dining dining) {
Account account = accountRepository.findByCreditCard(dining.getCreditCardNumber());
Restaurant restaurant = restaurantRepository.findByMerchantNumber(dining.getMerchantNumber());
MonetaryAmount amount = restaurant.calculateBenefitFor(account, dining);
AccountContribution contribution = account.makeContribution(amount);
accountRepository.updateBeneficiaries(account);
return rewardRepository.confirmReward(contribution, dining);
}
因此,此方法对某些服务类(基本上在数据库上执行某些查询)执行某些操作。我希望所有这些操作都执行到一个事务中(这保证了ACID属性)所以我使用 @Transactional 注释来注释这个方法。好的,我认为这对我来说非常清楚。
My Spring项目分为2个主文件夹(我认为是2个目录),包含相同的包)。这些文件夹分别命名为 src / test / java 和 src / main / java 。第一个包含与 JUnit测试相关的类,第二个包含与实现应用程序的正确项目相关的类,这是如何组织我的项目的屏幕截图:
好的,现在在练习中它说我必须定义一个名为 transactionManager 的bean,它配置一个 DataSourceTransactionManager ,将此方法添加到名为的Spring配置类中rewards.SystemTestConfig 位于 src / test / java 文件夹中:
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
因此,我很清楚这个方法配置了一个名为 transactionManager 的bean,该bean由 DataSourceTransactionManager 实现,使用 DataSource 对象。 / p>
我怀疑与此配置的位置有关。事实上,它被放在 src / test / java 文件夹中的 rewards.SystemTestConfig 内(包含 JUnit内容的文件夹。
所以我的怀疑是:这种配置是仅与测试环境相关还是对我的整个项目来说是全局的? ( transactionManager 仅适用于测试环境,还是用于我的具体应用程序?)
我在 src / main / java 文件夹中有另一个配置类,这个:
package config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import rewards.RewardNetwork;
import rewards.internal.RewardNetworkImpl;
import rewards.internal.account.AccountRepository;
import rewards.internal.account.JdbcAccountRepository;
import rewards.internal.restaurant.JdbcRestaurantRepository;
import rewards.internal.restaurant.RestaurantRepository;
import rewards.internal.reward.JdbcRewardRepository;
import rewards.internal.reward.RewardRepository;
// TODO-03: Add an annotation to instruct the container to look for the
// @Transactional annotation. Save all work, run RewardNetworkTests. It should pass.
@Configuration
@EnableTransactionManagement
public class RewardsConfig {
@Autowired
DataSource dataSource;
@Bean
public RewardNetwork rewardNetwork(){
return new RewardNetworkImpl(
accountRepository(),
restaurantRepository(),
rewardRepository());
}
@Bean
public AccountRepository accountRepository(){
JdbcAccountRepository repository = new JdbcAccountRepository();
repository.setDataSource(dataSource);
return repository;
}
@Bean
public RestaurantRepository restaurantRepository(){
JdbcRestaurantRepository repository = new JdbcRestaurantRepository();
repository.setDataSource(dataSource);
return repository;
}
@Bean
public RewardRepository rewardRepository(){
JdbcRewardRepository repository = new JdbcRewardRepository();
repository.setDataSource(dataSource);
return repository;
}
}
正如您所看到的,它不包含 transactionManager bean的显式配置,但它使用 @EnableTransactionManagement 注释进行了注释。我知道这个注释定义了一个代理@Transactional bean的Bean后处理器,因此发生了:
包含在代理中的目标对象(使用环绕建议)
代理实现以下行为:在输入方法之前启动事务并且在方法结束时提交并且如果方法抛出RuntimeException则回滚
但是我无法理解为什么在测试环境的 rewards.SystemTestConfig 配置类中,它显式地声明了 transactionManager bean并且在中RewardsConfig 类(配置正确应用程序的类)它没有被声明为 transactionManager (我认为这个bean绝对需要与事务一起运行)但是在它的位置有< strong> @EnableTransactionManagement 注释。
所以我怀疑是:
1)将 transactionManager bean声明为测试环境的 rewards.SystemTestConfig 配置类,它是全局的,它也适用于正确的应用程序文件夹(但我不是&# 39; t think)。
2)注意 @EnableTransactionManagement 注释 rewards.SystemTestConfig (配置正确的应用程序),它会自动创建一个事务管理器。但是什么样的?尤其是你怎么知道应该使用哪个数据源?
你能帮助我理解它是如何工作的吗?我错过了什么?