spring在构造器注入时报错,类型不匹配

本文详细解析了在Spring框架中使用构造器注入时出现的Bean创建异常问题,并提供了具体的解决方案。通过调整XML配置文件中的参数类型,成功解决了构造器参数类型的匹配问题。

====================================>User.java

public class User {

private Integer id;

private String name;

private Integer age;

 

public User(){}

public User(Integer id, String name, Integer age) {

super();

this.id = id;

this.name = name;

this.age = age;

}

 

public Integer getId() {

return id;

}

//setter and getter method ......

}

===================================================>Test.java

@org.junit.Test

public void testCase(){

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

User user = (User)context.getBean("user");

System.out.println(user.getId()+":"+user.getName()+":"+user.getAge());

}

=====================================>applicationContext.xml

<bean id="user" class="com.ustcinfo.entity.User">

<constructor-arg index="0" type="int">

<value>1</value>

</constructor-arg>

<constructor-arg index="1" type="java.lang.String">

<value>scott</value>

</constructor-arg>

<constructor-arg index="2" type="java.lang.Integer">

<value>30</value>

</constructor-arg>

</bean>

用set方式不会报错,但是用构造器缺报错了:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'user' defined in class path resource [applicationContext.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)

at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:250)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1049)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)

at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)

at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)

at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)

at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)

at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)

at com.ustcinfo.entity.Test.testCase(Test.java:11)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:606)

at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)

at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)

at org.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)

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.junit.runners.ParentRunner.run(ParentRunner.java:309)

at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)

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)

======================================>解决方案

看到红色加粗字体没?注意将type属性删除,只留一个index属性也是可以的(构造函数非重载的情况下),当然不删除最好,避免重载时出错,最好的解决办法是index和type同时配置。下面我来解释下为何添加上type属性后报错:注意我的实体类User中属性id是Integer类型,而applicationContext.xml中配置的是int,所以解决办法有两种,其一,将User中id类型改为int类型,其二,或者改applicationContext.xml配置为type="java.lang.Integer"

历史记录 avater E:\WFWlesson\code\redis-demo\src\test\java\com\heima\redisdemo\RedisDemoApplicationTests.java:27:52 java: 无法将类 com.heima.redisdemo.redis.pojo.User中的构造器 User应用到给定类型; 需要: 没有参数 找到: java.lang.String,int 原因: 实际参数列表和形式参数列表长度同 回答 在Java中,构造器参数匹配导致的编译错误通常是因为尝试实例化一个类提供的参数与该类定义的构造方法匹配。具体来说,在用户提到的问题中,“constructor User in class com.heima.redisdemo.redis.pojo.User cannot be applied to given types; required no arguments but found String and int”,表明试图使用字符串和整数作为参数调用User类的构造函数,但该类没有接受这些参数类型的构造方法。 解决方案 检查类定义 首先确认User类是否有接受字符串和整数类型参数的构造方法。例如: Java public class User { private String name; private int id; // 默认无参构造方法 public User() {} // 带有参数的构造方法 public User(String name, int id) { this.name = name; this.id = id; } // 其他属性和方法... } 如果没有这样的构造方法,则需要添加它4。 修改实例化方式 如果无法更改User类的定义,确保在创建对象使用的参数与现有构造方法匹配。例如,如果只有默认构造方法,则应使用new User()来创建实例。 使用setter方法赋值 如果只能使用默认构造方法,可以在创建对象后通过setter方法设置属性值: Java User user = new User(); user.setName("John Doe"); user.setId(1); 考虑Lombok插件简化代码 使用Lombok插件可以减少样板代码,比如自动为类生成getter、setter以及构造方法等。只需在类或字段上添加注解即可实现功能增强。 验证框架兼容性 若项目中涉及Spring或其他依赖注入框架,确保实体类的设计符合框架要求,尤其是对于转换器的支持情况5。有候可能需要注册特定的转换器以支持类型之间的转换。 重构已有代码 对于已经存在的类及其构造方法,若发现设计合理或者存在冗余,可适当进行重构优化,使得类更加健壮易用。 以上措施有助于解决由于构造器参数匹配引发的问题,并提高代码质量和维护性。 相关提问 . 如何正确使用Lombok简化Java实体类? . 在Spring Boot应用中如何处理类型转换异常? . Java中同访问修饰符对构造方法的影响是什么? 思维导图 参考来源 优快云 优快云 优快云 优快云 优快云 我已经用了Lombok了 回答 问题分析 当用户在使用Lombok遇到构造器参数匹配的编译错误,可能的原因包括: Lombok未正确生成所需的构造方法。 使用了@Builder注解导致默认构造方法失效。 编译环境配置当,导致Lombok处理器无法正常工作。 解决方案 1. 确保Lombok正确生成构造方法 如果类中使用了@Data或@AllArgsConstructor等注解,但仍然出现构造器参数匹配的问题,需要检查是否同使用了@Builder。根据已知信息,@Builder会导致@Data中的构造方法失效,此必须显式添加@NoArgsConstructor和@AllArgsConstructor来确保无参和全参构造方法被正确生成 3。例如: Java import lombok.*; @Data @ToString @Builder @NoArgsConstructor @AllArgsConstructor public class User { private String name; private int id; } 上述代码将确保User类包含无参构造方法和全参构造方法,从而避免构造器参数匹配的问题。 2. 检查Lombok是否因编译器兼容性问题失效 如果提示“lombok.javac.apt.LombokProcessor could not be initialized”或“You aren’t using a compiler supported by lombok”,说明Lombok可能未成功初始化,导致其注解处理器未能运行。这种情况通常发生在使用兼容的编译器(如某些IDE插件版本)。解决办法包括: 更新Lombok版本至最新稳定版以支持当前编译环境。 确保项目构建工具(如Maven或Gradle)与IDE使用的JDK版本一致,并且为Lombok支持的版本。 在IDE中手动安装并启用Lombok插件(如IntelliJ IDEA需额外安装Lombok插件) 1。 3. 验证构造方法是否私有或可访问 对于某些框架(如FastJSON),若类没有公开的默认构造方法,可能会导致序列化/反序列化失败。Lombok从1.16.22版本起会生成私有的默认构造方法,这可能导致解析报错。建议显式声明构造方法或通过反射设置其可访问性 4。 4. 显式定义构造方法 如果Lombok未能按预期生成构造方法,可以考虑直接在类中定义构造方法以确保编译可用性。例如: Java public class User { private String name; private int id; public User() {} public User(String name, int id) { this.name = name; this.id = id; } } 这样即使Lombok未生效,也能保证构造方法存在,避免编译错误。 总结 构造器参数匹配问题的根本原因可能是Lombok未正确生成构造方法、构造方法被其他注解影响或Lombok未正常运行。通过检查注解组合、更新Lombok版本、验证编译器兼容性以及显式定义构造方法等方式,可以有效解决此类问题。 相关提问 如何在Spring Boot项目中正确使用Lombok简化实体类? Lombok的`@NoArgsConstructor`和`@AllArgsConstructor`有什么区别? 使用`@Builder`为何需要显式指定构造方法? 思维导图 参考来源 优快云 优快云 优快云 优快云 我的idea是2024.1.4版本的,兼容哪个版本的Lombok
07-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值