Java 由于自动连接字段,BeanNotOfRequiredTypeException
我还是Spring MVC的新手,在构建我的测试项目时,我从Tomcat日志中得到了以下信息:Java 由于自动连接字段,BeanNotOfRequiredTypeException,java,spring-mvc,annotations,tomcat7,Java,Spring Mvc,Annotations,Tomcat7,我还是Spring MVC的新手,在构建我的测试项目时,我从Tomcat日志中得到了以下信息: SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException: Error cre
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'divisionController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'adminService' must be of type [employee.service.impl.AdminServiceImpl], but was actually of type [$Proxy52]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:307)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'adminService' must be of type [employee.service.impl.AdminServiceImpl], but was actually of type [$Proxy52]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:360)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
我有两个用于用户和管理员的rolle服务,有三个接口:
package employee.service;
import employee.model.EmployeeDiv;
import employee.model.EmployeeInfo;
import employee.model.UserInfo;
import java.util.List;
/**
*
* @author serge
*/
public interface AdminService extends UserService {
// !!!! for register & udate of Employee use String type birthday !!!!
/*
* Employee
*/
public EmployeeInfo registerEmployee(EmployeeInfo employeeInfo);
public EmployeeInfo updateEmployee(EmployeeInfo employeeInfo);
public EmployeeInfo findEmployeeByID(Integer id);
/*
* Division
*/
public EmployeeDiv registerDivision(EmployeeDiv division);
public EmployeeDiv updateDivision(EmployeeDiv division);
public List<EmployeeDiv> findAllDivisions();
public List<EmployeeDiv> findDivisionsByName(EmployeeDiv division);
public EmployeeDiv findDivisionsById(Integer id);
/*
* Login
*/
public UserInfo registerUser(UserInfo user);
public UserInfo updateUser(UserInfo user);
public List<UserInfo> findAllUsesrs();
public List<UserInfo> findUsesrByLogin(UserInfo user);
public UserInfo findUsesrById(Integer id);
}
我如何修复它?
我在控制器中使用AdminServiceImpl:
package employee.controller;
import employee.model.EmployeeDiv;
import employee.service.impl.AdminServiceImpl;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.annotation.Resource;
/**
* @author serge
*
* Handles and retrieves division related requests
*/
@Controller
@RequestMapping("/division")
public class DivisionController {
protected static Logger logger = Logger.getLogger("controller");
@Resource(name = "adminService")
private AdminServiceImpl adminService;
/**
* Handles and retrieves a /WEB-INF/jsp/divisionpage.jsp
*
* containing all division
*
* @return the name of the JSP page
*/
@RequestMapping(method = RequestMethod.GET)
public String getAllPage(Model model) {
logger.debug("Received request to show all division page");
// Retrieve all division and attach to model
model.addAttribute("division", adminService.findAllDivisions());
return "divisionpage";
} ....
在代码中的某个地方,您必须像这样自动连接
AdminServiceImpl
:
@Autowired
private AdminServiceImpl adminService;
两种方法都几乎不依赖于接口:
@Autowired
private AdminService adminService;
或启用CGLIB代理
类似问题
AdminService
而不是工具
这个错误是由注释
@Transactional
,Spring
在运行时为AdminService
创建一个代理引起的。当您的服务类实现一些接口时,Spring默认由JDK代理,这就是为什么会出现这个错误,因此,无论是在接口上使用@Autowired还是启用CGLIB代理,都可以解决这个问题
我解决了在spring应用程序上下文中使用代理目标类属性启用CGLIB代理的问题
<tx:annotation-driven proxy-target-class="true"
transaction-manager="transactionManager" />
我也面临同样的问题,但我通过以下解决方法解决了这个问题:
请用接口替换您的实现类。
例如:
class Abc
{
@Autowire
private Boy boy // remove @BoyImpl
.............
...................
}
在谷歌搜索我的问题时,我发现了很多类似的问题。然而,在我的例子中,我已经使用了一个接口。因此我认为这可能对其他人有所帮助:
如果您有两个同名的bean,也可能出现此异常强>
在我的例子中,applicationContext.xml中有额外的bean配置。问题出现在我合并两个应用程序之后。第二个定义了一个@Resource
,其成员变量名与上面提到的第一个应用程序的bean名匹配。当然,第一个应用程序的bean配置不适合第二个应用程序通过@Resource
包含的bean。我在执行单元测试时也遇到了这个问题
我创建了一个模拟服务来实现真正的服务,以覆盖一些方法,以便测试一些用户案例
@Component
public static class FooServiceImplMock extends FooServiceImpl {
@Override
protected void bar() {
// do some specific loginc here
}
}
但是当执行测试方法时
@Autowired
private Foo1ServiceImplMock foo1ServiceImplMock;
我犯了以下错误
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'fooServiceImplTest.FooServiceImplMock' is expected to be of type 'com.foo.business.impl.FooServiceImplTest$FooServiceImplMock' but was actually of type 'com.sun.proxy.$Proxy97'
原因:
在FooServiceImpl中使用了@Cacheable方法
@Cacheable("eventTypes")
从EnableCaching的javadoc我知道
org.springframework.cache.annotation.EnableCaching
boolean proxyTargetClass()
Indicate whether subclass-based (CGLIB) proxies are to be created as opposed to standard Java interface-based proxies. The default is false.
因此,解析方式是显式地指定在spring应用程序contenxt中使用CGLIB
<cache:annotation-driven proxy-target-class="true"/>
我在测试端点的一些@SpringBootTest
类中也遇到了这个问题。端点依赖于在一些方法上具有@Transactional
的DB服务
由于@Transactional
,Spring截取并创建了一个代理类,因此Spock(或junit)很难注入正确的mock
我的解决方法是将DB服务向下推一层,并在中间层进行简单的Spock测试,而不受此影响。当对现有类的测试开始失败时,我遇到了这个问题,测试的类型是“预期为……但实际上为'com.sun.proxy.$Proxy115'
结果是,我在添加到接口实现类的@Transactional方法上使用了Intellij的“pull method up[to interface]”,Intellij决定将@Transactional添加到接口方法声明中。如果一个接口中只有一个@Transactional方法,那么它似乎会把事情搞砸,导致此错误。请确保已在上启用proxyTargetClass,如:
@EnableTransactionManagement(proxyTargetClass = true)
@谢尔盖:你可以自己修,这是个常见的问题。只要查找类型为AdminServiceImpl
的自动连接字段,我很确定您有一些。也就是说,查找您实际使用的位置AdminServiceImpl
。删除Impl
以仅依赖接口。就这样!删除Impl以仅依赖于接口。如果我替你表演?我必须重新使用AdminService使用的所有AdminServiceImpl。@Serge:的确如此。事实上,如果仍然依赖类,为什么要将类和接口分开?…Impl
出现的唯一位置是类定义中,而不是其他地方。请告诉我有关“autowire”的信息。如何正确地自动连接字段?我应该在接口中这样做,还是一切都做对了?使用接口而不是实现,并用@Qualifier注释以获得正确的类。救了我的命!非常感谢。伟大的你的建议正好解决了我的问题。不确定为什么有人投了反对票。或者如果您将@EnableTransactionManagement
添加到配置中作为结果@Transactional
开始工作。为了我
org.springframework.cache.annotation.EnableCaching
boolean proxyTargetClass()
Indicate whether subclass-based (CGLIB) proxies are to be created as opposed to standard Java interface-based proxies. The default is false.
<cache:annotation-driven proxy-target-class="true"/>
@EnableTransactionManagement(proxyTargetClass = true)