这一部分涉及到spring+spring mvc +mybatis整合中出现的非常头疼的bug,是autowired注入失败,在使用接口实现还是,继承实现的方式上mybatis与spring mvc 都各自有不同的方式:
比如第一个头等级的bug是:由于autowired注解虽然在被扫描到了,但是无法实例化,导致项目无法进行。
我将错误复现,然后尝试解释其中的原理:
<!-- 扫描basePackage下所有以@MyBatisRepository标识的接口-->
<beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer">
<propertyname="basePackage"value="cn.com.bugwebapp"/>
<propertyname="sqlSessionFactoryBeanName"value="sqlSessionFactory1"/>
<propertyname="annotationClass"value="cn.com.bugmanger.mybatis.annotation.mybatisRepository"/>
</bean>
java.lang.IllegalStateException: Failed toload ApplicationContext
atorg.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContex
t(DefaultCacheAwareContextLoaderDelegate.java:91)~[spring-test-
4.1.0.RELEASE.jar:4.1.0.RELEASE]
at
。。。。。。。。。。。。。
Caused by:org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'bugAnswerController':Injection of autowired dependencies failed;
nested exception isorg.springframework.beans.factory.BeanCreationException: Could
not autowire field: protectedcn.com.bugmanger.bugcontent.service.BugAnswerService
cn.com.bugwebapp.bugContent.BugAnswerController.bugAnswerService;nested exception
isorg.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'bugAnswerService': Injection ofautowired dependencies failed; nested
exception is org.springframework.beans.factory.BeanCreationException:Could not
autowire field: privatecn.com.bugmanger.bugcontent.dao.BugAnswerDao
cn.com.bugmanger.bugcontent.service.BugAnswerService.bugAnswerDao;nested
exception isorg.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type[cn.com.bugmanger.bugcontent.dao.BugAnswerDao] found for
dependency: expected at least 1 bean whichqualifies 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:326)~
[spring-beans-4.1.0.RELEASE.jar:4.1.0.RELEASE]
at
这些bug信息已经足够了,
上面那段配置是错误的。有过开发经验的人已经看出来了。
首先理清一下思路,BugAnswerDao 是mybatis的mapper.xml对应的接口使用注解进行接口扫描进行注入:
这个注解标示在mapper接口上,当然在我上网寻找答案的过程中还有另外的实现方式:
就是定义一个空的splhelper 接口,里面什么方法也不写,让其他mapper接口继承这个空的接口,然后将这个空的接口放在spring的bean中进行注入。
这里是使用注解的方式,当然更简洁点。
有趣的是,我在另一个包中也同样声明了这个注解,但是这个注解并没有左边带叶子的D符号,于是就说明了那个配置文件没有起到扫描的作用,或者准确的说扫描的路径是错误的,没有扫描到标示mybatisRepository的接口,当然一开始就没有意识到这一点。
所以在Controller层进行注入的时候,BugAnswerService没有注入成功由于bugAnswerService 依赖的BugAnswerDao没有注入成功,导致bugAnswerDao 没有实例化,方法也无从谈起,在spring 容器初始化的时候,bean始终没有得以实例化,从而一直提示创建service的bean一直失败。所以正确的扫描路径是将
<property name="basePackage"value="cn.com.bugwebapp"/>改为:
Mapper接口所在的包下面:
<property name="basePackage" value="cn.com.bugmanager"/>
这之后基本就比较好解决了,
java.lang.NullPointerException
atcn.com.bugmanger.securityTest.UserServiceTest.testAddUser
(UserServiceTest.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)
at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:43)
atorg.junit.runners.model.FrameworkMethod$1.runReflectiveCall
(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run
(ReflectiveCallable.java:12)
atorg.junit.runners.model.FrameworkMethod.invokeExplosively
(FrameworkMethod.java:44)
atorg.junit.internal.runners.statements.InvokeMethod.evaluate
(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild
(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild
(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
atorg.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
atorg.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
atorg.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
atorg.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
atcom.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
Disconnectedfrom the target VM, address: '127.0.0.1:50824', transport: 'socket'
解决方式
没有继承抽象测试类。空指针异常,应该是切面事务和数据源没有值。
这个是Controller参数以及注解的装配问题:
问题六:说明,spring mvc 不能创建bean,
Causedby: org.springframework.beans.factory.BeanCreationException: Error creating
beanwith name
'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMappin
g#0':Invocation of init method failed; nested exception is
java.lang.IllegalStateException:Ambiguous mapping found. Cannot map
'bugAnswerController'bean method
publiccn.com.bugmanger.ajax.response.AjaxResponse
cn.com.bugwebapp.bugContent.BugAnswerController.addBugAnswer
(cn.com.bugmanger.bugcontent.model.BugAnswer,org.springframework.validation.Bindin
gResult,javax.servlet.http.HttpServletRequest)
to{[/bug/buganswer],methods=[POST],params=[],headers=[],consumes=[],produces=
[],custom=[]}:There is already 'bugAnswerController' bean method
publiccn.com.bugmanger.common.ajax.DataTablesResponse
cn.com.bugwebapp.bugContent.BugAnswerController.getBugAnswerListPage
(int,cn.com.bugmanger.bugcontent.model.BugAnswer)mapped.
at org.springframework.beans.facto
解决指导:
controller映射地址不一致
方法参数,请求类型,等
下面这两个问题时在测试的时候出现的,当抛出异常的时候,表明某些测试类会依赖部分包,这些包没有被引入pom.xml的时候就会出错,一般都是类的异常没找到,或者相关类没有找到,或者异常信息中要求你加入相关依赖,才可能好使。
问题1七:
maven中依赖的传递性问题
cher.java:308)
atjava.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 31 more
java.lang.NoClassDefFoundError:com/jayway/jsonpath/InvalidPathException
at
org.springframework.test.web.servlet.result.JsonPathResultMatchers.<init>
(JsonPathResultMatchers.java:43)
at
org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
(MockMvcResultMatchers.java:183)
at
cn.com.bugmanager.webtest.TagTypeControllerTest.TagTypeControllerTest.testAddTagTy
pe(TagTypeControllerTest.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)
at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:43)
atorg.junit.runners.model.FrameworkMethod$1.runReflectiveCall
(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run
(ReflectiveCallable.java:12)
atorg.junit.runners.model.FrameworkMethod.invokeExplosively
(FrameworkMethod.java:44)
atorg.junit.internal.runners.statements.InvokeMethod.evaluate
(InvokeMethod.java:17)
atorg.junit.internal.runners.statements.RunBefores.evaluate
(RunBefores.java:26)
at
org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.ev
aluate(RunBeforeTestMethodCallbacks.java:72)
at
org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.eva
luate(RunAfterTestMethodCallbacks.java:81)
at
org.springframework.test.context.junit4.statements.SpringRepeat.evaluate
(SpringRepeat.java:72)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild
(SpringJUnit4ClassRunner.java:216)
at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild
(SpringJUnit4ClassRunner.java:82)
atorg.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
atorg.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
atorg.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
atorg.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at
org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.eva
luate(RunBeforeTestClassCallbacks.java:60)
at
org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.eval
uate(RunAfterTestClassCallbacks.java:67)
atorg.junit.runners.ParentRunner.run(ParentRunner.java:309)
atorg.springframework.test.context.junit4.SpringJUnit4ClassRunner.run
(SpringJUnit4ClassRunner.java:162)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
atcom.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
Causedby: java.lang.ClassNotFoundException:
com.jayway.jsonpath.InvalidPathException
atjava.net.URLClassLoader$1.run(URLClassLoader.java:366)
atjava.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(NativeMethod)
atjava.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
atsun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
atjava.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 31 more
解决方法:这是spring -test 相关测试的时候使用mock mvc 进行测试的时候出现的问题,是
spring-test框架和mock相关的依赖没有添加入。
<!--mock mvc 测试相关包-->
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>1.8.0</version>
<scope>test</scope>
</dependency>
<!--如果需要打包groovy就需要加入org.codehaus.groovy依赖-->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>${json-path.version}</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<!--mock 测试相关包结束-->
问题八:
maven中测试相关依赖没有导入
Causedby: javax.validation.ValidationException: HV000183: Unable to load
'javax.el.ExpressionFactory'.Check that you have the EL dependencies on the
classpath
at
org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<in
it>(ResourceBundleMessageInterpolator.java:172)~[hibernate-validator-
5.1.2.Final.jar:5.1.2.Final]
at
org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<in
it>(ResourceBundleMessageInterpolator.java:118)~[hibernate-validator-
5.1.2.Final.jar:5.1.2.Final]
atorg.hibernate.validator.internal.engine.ConfigurationImpl.<init>
(ConfigurationImpl.java:110)~[hibernate-validator-5.1.2.Final.jar:5.1.2.Final]
at org.hibernate.validator.internal.engine.ConfigurationImpl.<init>
(ConfigurationImpl.java:86)~[hibernate-validator-5.1.2.Final.jar:5.1.2.Final]
atorg.hibernate.validator.HibernateValidator.createGenericConfiguration
(HibernateValidator.java:41)~[hibernate-validator-5.1.2.Final.jar:5.1.2.Final]
atjavax.validation.Validation$GenericBootstrapImpl.configure
(Validation.java:276)~[validation-api-1.1.0.Final.jar:na]
... 48 common frames omitted
Causedby: org.springframework.beans.factory.BeanCreationException: Error creating
beanwith name 'validator' defined in class path resource
[applicationContext.xml]:Invocation of init method failed; nested exception is
javax.validation.ValidationException:Unable to instantiate Configuration.
hibernate.validate可能要依赖el表达式
javax.el表达式相关依赖没有导入