【发布时间】:2021-06-08 11:38:08
【问题描述】:
我有一个需要不可变和单例的人模型类。我需要从我的服务类中自动装配,但出现错误。
那么有什么方法可以在 Spring Boot 中创建一个单例不可变类?我可以亲自设置值(通过自动连接)并在整个应用程序中使用相同的值。
我刚开始学习spring-boot。我在谷歌上搜索并找到了 Lombok 的解决方案,但不知何故它对我不起作用。
我的人物模型:
@Value
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Component
public final class Person {
private final String firstName;
private final String lastName;
}
//My service class
@Component
public class ArgumentReadingService {
@Autowired
Person person;
public void readArguments() {
person = Person.builder().firstName("Hello").build();
System.out.println("name : "+person.getFirstName());
}
错误:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-03-10 17:52:29.197 ERROR 8824 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'person' defined in file [C:\Users\User\Desktop\WorkSpace\Orion.Strat1.bidAsk_Stp\target\classes\orion\model\Person.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [orion.model.Person]: No default constructor found; nested exception is java.lang.NoSuchMethodException: orion.model.Person.<init>()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1316) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:582) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) [spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) [spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) [spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) [spring-boot-2.4.3.jar:2.4.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) [spring-boot-2.4.3.jar:2.4.3]
at com.orion.Application.main(Application.java:20) [classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [orion.model.Person]: No default constructor found; nested exception is java.lang.NoSuchMethodException: orion.model.Person.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83) ~[spring-beans-5.3.4.jar:5.3.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1308) ~[spring-beans-5.3.4.jar:5.3.4]
... 17 common frames omitted
Caused by: java.lang.NoSuchMethodException: orion.model.Person.<init>()
at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_191]
at java.lang.Class.getDeclaredConstructor(Class.java:2178) ~[na:1.8.0_191]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78) ~[spring-beans-5.3.4.jar:5.3.4]
... 18 common frames omitted
【问题讨论】:
-
您希望 Spring 从哪里获取 Person 的名字和姓氏?此外,您已将构造函数指定为私有。 Spring 可能能够通过反射解决这个问题,但它很可能会忽略任何私有构造函数。无论哪种方式都绝对是代码味道,因为如果您愿意,您将无法为其编写单元测试。
-
模型类应该不是一个单例;它们实际上是每个请求的特定数据。
-
Builder 模式和 Singleton 并不完全相同。如果您允许您的 Builder 创建无数实例,则将您的构造函数设为私有并不会使其成为单例。
标签: java spring spring-boot autowired lombok