如何在事务类上自动装配

如何在事务类上自动装配

本文介绍了如何在事务类上自动装配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类文件:

  @Transactional(propagation = Propagation.REQUIRES_NEW)
public class ServiceImpl implements Service {
...
}

Xml档案:

  ... 
...

测试文件:

  @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(testConfig.xml)
public class ServiceImplTest {

private static final Logger log = Logger
.getLogger(ServiceImplTest.class);

@Autowired
私人ServiceImpl服务;

@Test
public void test(){
...
}

例外:

  org.springframework.beans.factory.BeanCreationException:创建bean时出错名称为'com.sky.core.engine.comp.impl.ServiceImplTest':注入自动装配的依赖关系失败;嵌套异常是org.springframework.beans.factory.BeanCreationException:无法自动装入字段:private com.sky.core.engine.impl.ServiceImpl com.sky.core.engine.impl.Service;嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到符合依赖关系的[com.sky.core.engine.comp.impl.ServiceImpl]类型的合格bean:期望至少1个符合此依赖关系的autowire候选者的Bean 。依赖注解:{@ org.springframework.beans.factory.annotation.Autowired(所需=真)} 
。在org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
。在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146)
在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:376)
。在org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
在org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
在org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager。 java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner $ 1.runReflectiveCall(SpringJUnit4ClassRunner .java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner的.java:290)
。在在org.junit.runners.BlockJUnit4ClassRunner.runChild org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
(BlockJUnit4ClassRunner.java:50 )
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)
在org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.junit.runners.parentRunner.run(ParentRunner.java:309)
org。org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
在org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
。在org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(R
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
引起:org.springframework.beans.factory.BeanCreationException:无法自动装入字段:private com.sky.core.engine.impl.ServiceImpl.ServiceImpl com.sky.core.engine.impl.ServiceImpl;嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到符合要求的[com.att.lpp.pa1.core.engine.comp.impl.EndPointServiceImpl]类型的符合条件的bean:期望至少1个符合autowire这种依赖的候选人。依赖注解:{@ org.springframework.beans.factory.annotation.Autowired(所需=真)}
。在org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
... 26 more
导致:org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到符合条件的[com.sky.core.engine.comp.impl.ServiceImpl]类型的合格bean:expected至少有1个bean有资格作为这个依赖关系的autowire候选。依赖注解:{@ org.springframework.beans.factory.annotation.Autowired(所需=真)}
。在org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988)
。在org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858)
在org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
在org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
... 28 more

如果我从类文件中删除 @Transactional(propagation = Propagation.REQUIRES_NEW),那么它将允许我自动装入我的类目的。我想知道是否有自动装配交易?可能是由于它的类型,但我不知道这是一个怎样的事务。

解决方案

如果你添加Transactional注释到你的类,Spring将为该类创建一个代理来执行事务逻辑。如果bean实现了一个接口,Spring将创建一个基于JDK的代理来实现bean的所有接口。因此,代理的类型在你的情况下是 Service ,而不是 ServiceImpl



有两种解决方案:

1:
将autowired字段的字段类型更改为界面:

  @Autowired 
私人服务服务;



:配置Spring以使用基于CGLIB的代理。这些代理扩展了bean类,因此它们与bean类本身具有相同的类型。这可以通过下面的注解来完成,它是属性,如果你使用它:

  @EnableTransactionManagement(proxyTargetClass = true)

或者如果您对事务管理器使用XML配置:

 < tx:annotation-driven proxy-target-class =truetransaction-manager =txManager/> 

您可以阅读更多关于Spring文件中的代理等的信息:

Class file:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public class ServiceImpl implements Service {
...
}

Xml file:

...
<bean id="service" class="com.sky.core.engine.impl.ServiceImpl">
...

Test File:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("testConfig.xml")
public class ServiceImplTest {

    private static final Logger log = Logger
            .getLogger(ServiceImplTest.class);

    @Autowired
    private ServiceImpl service;

    @Test
    public void test(){
       ...
    }

Exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.sky.core.engine.comp.impl.ServiceImplTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.sky.core.engine.impl.ServiceImpl com.sky.core.engine.impl.Service; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.sky.core.engine.comp.impl.ServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:376)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    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:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.sky.core.engine.impl.ServiceImpl.ServiceImpl com.sky.core.engine.impl.ServiceImpl; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.att.lpp.pa1.core.engine.comp.impl.EndPointServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
    ... 26 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.sky.core.engine.comp.impl.ServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
    ... 28 more

If I remove @Transactional(propagation=Propagation.REQUIRES_NEW) from the Class file then it will allow me to autowire my class object. I was wondering is there to autowire a transactional? maybe by its type but I don't know how as this is a transactional.

解决方案

If you add the Transactional annotation to your class, Spring will create a proxy for that class to do the transaction logic. If the bean implements an interface, Spring will create a JDK based proxy which implements all interfaces of the bean. Thus the type of the proxy is in your case Service and not ServiceImpl.

There are 2 solutions:

1:Change the field type of the autowired field to the interface:

@Autowired
private Service service;

2: Configure Spring to use CGLIB based proxies. Those proxies extend the bean class and so they have the same type as the bean class itself. This can be done either with the following annotation and it's attribute, if you use that:

@EnableTransactionManagement(proxyTargetClass = true)

Or if you use XML configuration for the transaction manager:

<tx:annotation-driven proxy-target-class="true" transaction-manager="txManager"/>

You can read more about the proxies etc. in the Spring docu: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-decl-explained

这篇关于如何在事务类上自动装配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 09:02