当前位置: 首页 > 知识库问答 >
问题:

spring Java Config和@EnableTransactionManagement的问题

萧阳波
2023-03-14

我正在从XML配置迁移到spring上下文配置。相反,当我试图在spring 4.0.3.Release Java配置上使用功能等价的@EnableTransactionManagement时,我的spring上下文无法实例化,但有以下例外:

java.lang.IllegalStateException: Failed to load ApplicationContext
        at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
        at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
        at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:319)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:212)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:236)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:134)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:113)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:103)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:74)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseMySQLTest.TestConfig': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.config.internalTransactionAdvisor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.transaction.intercep...skipping...
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1558)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
        ... 45 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration.transactionAdvisor()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionInterceptor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'transactionManager' is required
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586)
        ... 62 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionInterceptor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'transactionManager' is required
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
        at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:324)
        at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634.transactionInterceptor()
        at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration.transactionAdvisor(ProxyTransactionManagementConfiguration.java:45)
        at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634.CGLIB$transactionAdvisor$0()
        at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634$$FastClassBySpringCGLIB$$cc829ae.invoke()
        at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
        at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
        at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634.transactionAdvisor()
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
        ... 63 more
Caused by: java.lang.IllegalArgumentException: Property 'transactionManager' is required
        at org.springframework.transaction.interceptor.TransactionAspectSupport.afterPropertiesSet(TransactionAspectSupport.java:195)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
        ... 82 more

这恰好在单元测试中获得,但当它在这里工作时,我可以在生产代码中使用它。

下面是我的单元测试基类,其中发生了spring布线:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PropertyPlaceholderConfigurer.class, BaseMySQLTest.TestConfig.class})
public class BaseMySQLTest extends AbstractTransactionalJUnit4SpringContextTests {

    @Configuration
    @Import(DaoConfig.class)
    @PropertySource("classpath:/jdbc.properties")
    @EnableTransactionManagement
    public static class TestConfig {
        @Bean
        public PlatformTransactionManager providesTransactionManager(ListableBeanFactory beanFactory) {
            return new DataSourceTransactionManager(beanFactory.getBean(DataSource.class));
        }
    }
}

下面是使用此基类和配置的子类:

public class UserDaoImplTest extends BaseMySQLTest {

    @Autowired
    private UserDao userDao;

    @Test
    public void testById() throws Exception {
        jdbcTemplate.execute("insert into users (email) values ('bob@example.com')");
        ...
    }

}

可以看到,我的spring TestConfig定义了一个事务管理器bean,它根据Javadoc

http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/transaction/annotation/enabletransactionmanagement.html

意味着我不必为bean命名(尽管我为它命名是为了使其工作)。事实上,在没有显式命名为“TransactionManager”的bean的情况下,spring上下文的行为就好像是用XML配置进行配置的。

我的Java配置缺少了什么,以致于spring上下文无法使用这个事务管理器bean来满足它在实例化时的要求?

谢谢你的任何有益的观察。

编辑:

(我不确定这个编辑应该去哪里,所以我在这里试一下。ae6rt)

下面是新的测试类,它导致了与原始工作相同的错误:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {BaseMySQLTest.TestConfig.class})
public class BaseMySQLTest extends AbstractTransactionalJUnit4SpringContextTests {

    protected int lastInsertId() {
        return jdbcTemplate.queryForInt("select LAST_INSERT_ID()");
    }

    @Autowired
    private UserDao userDao;

    @Test
    public void testById() throws Exception {
        jdbcTemplate.execute("insert into mgdb.users (email) values ('bob@example.com')");
        int userId = lastInsertId();
        Optional xoomUserOptional = userDao.byId(userId);
        assertThat(xoomUserOptional.isPresent(), equalTo(true));
        XoomUser user = xoomUserOptional.get();
        assertThat(user.getEmailAddress(), equalTo("bob@example.com"));
    }

    @Configuration
    @Import(DaoConfig.class)
    @PropertySource("classpath:/jdbc.properties")
    @EnableTransactionManagement
    public static class TestConfig {
        @Bean
        public PlatformTransactionManager providesTransactionManager(ListableBeanFactory beanFactory) {
            return new DataSourceTransactionManager(beanFactory.getBean(DataSource.class));
        }
    }

}

我实际上不需要这里的属性配置

@ContextConfiguration(类={BaseMysqlTest.TestConfig.Class})

所以我把它去掉了。希望这符合这一轮的精神。

共有1个答案

司徒志
2023-03-14

看来唯一的更改应该是将事务管理器bean名称命名为“transactionmanager”:

public static class TestConfig {
    @Autowired
    private DataSource datasource;

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(datasource);
    }
}

编辑:

你能试试这些附加的东西吗:

.1.从此删除PropertyPlaceHolderConfigurer@ContextConfiguration(类={PropertyPlaceholderConfigurer.class,BaseMySqlTest.TestConfig.Class}),这不是PropertyPlaceholderConfigurer的使用方式,您必须这样做:

@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
    PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
    ClassPathResource resource = new ClassPathResource("/META-INF/spring/database.properties");
    placeholderConfigurer.setLocation(resource);
    return placeholderConfigurer;
}

同样,只是为了测试,你能不能把你的实际测试也移到基类,看看这些配置中的一个是否适合你。我在自己的机器上进行了测试,它似乎可以很好地与spring 4.0.2+配合使用。

 类似资料:
  • 问题内容: 我试图了解在多个JavaConfig上下文中放置注释的正确位置在哪里? 考虑以下情形:我在JPAConfig.java和AppConfig.java中具有服务bean集的JPA配置。然后,在RootConfig.java中编写整个应用程序配置。 我在JPAConfig.java中定义事务管理器,并启用对JPA存储库的扫描- 当这些暴露事务行为时,我将其放到JPAConfig上,并且它可

  • 在Spring Boot中需要吗?我做了些调查。有些人说你不需要它,因为Spring Boot已经启用了它,其他人说你必须明确地使用它。那怎么样了?

  • 我试图在fabric rocket chat上联系,但没有得到太多帮助,因此在SO上发布了它。我有以下疑问: 我们是否可以在链码内访问块高度(我知道这在客户端是可行的,但在链码内是否可能) 可以从链码中的正在进行的事务调用新事务吗? 想知道hyperledger Fabric中存储的数据的历史记录在哪里 我们可以根据链码中的transactionid进行查询吗? 在fabric链码中编写调度程序是

  • 我需要将给定的任何图像转换为字节数组,以满足加密要求。我正在使用JProgressBar监控所选图像较大时的转换进度: 我定义了一个类,它使用,如下所示: 不幸的是,这个错误发生了! 我不知道我的代码出了什么问题!在写这段代码之前,我读了和,但我觉得我遗漏了什么!我能得到一个有用的提示吗。 谢谢:)

  • 我有密码 在我的主要方法中 如果我运行程序,我会得到输出: 如果我取消注释setLayout,我会得到输出: 两个问题: 为什么在第一种情况下没有按预期工作?我不应该看到整个圆而不是它的一半吗? 为什么椭圆形在第二个输出中变成了三角形?

  • 我有一个设备驱动程序正在冻结操作系统。鼠标甚至不会移动。我正在尝试调试这个问题,我相信一个好的方法是将gdb与qemu一起使用,这是我以前从未使用过的两件事。有更好的方法吗? 因此,首先我需要用调试符号编译内核,我已经完成了。 现在,生成了一个名为vmlinux的新文件,它与源文件位于同一个文件夹中。我似乎还需要一个bzImage文件,这样我就可以运行新编译的内核,使用: 或者处于调试模式 我找不