Java使用饿汉式如何使用同类中从yml文件获取的配置?
题目描述
Java使用饿汉式如何使用同类中从yml文件获取的配置?
题目来源及自己的思路
准备测试文件上传功能,使用的是MinIo,想要编写一个工具类,来生成MinIoClient,然后获取到yml配置文件中MinIo相关的配置
相关代码
工具类
@Component
@Data
@Slf4j
public class MinioTool {
public static String URL;
public static String KEY;
public static String SECRET;
@Value(value = "${minio.url}")
public void setUrl(String url) {
URL = url;
}
@Value(value = "${minio.key}")
public void setkey(String key) {
KEY = key;
}
@Value(value = "${minio.secret}")
public void setBucketName(String secret) {
SECRET = secret;
}
private static MinioClient minioClient = new MinioClient.Builder().endpoint(URL).credentials(KEY, SECRET).build();
public static MinioClient getInstance() {
return minioClient;
}
public boolean bucketExists(String bucketName) {
boolean found = false;
try {
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
log.error("系统异常");
}
return found;
}
}
接口调用
@RestController
@RequestMapping("/image")
public class UploadController {
MinioClient minioClient = MinioTool.getInstance();
@PostMapping
public void uploads(@RequestParam("file") MultipartFile... multipartFiles) {
InputStream inputStream;
try {
for (MultipartFile multipartFile : multipartFiles) {
inputStream = multipartFile.getInputStream();
ObjectWriteResponse test = minioClient.putObject(PutObjectArgs.builder()
.bucket("test").object(multipartFile.getOriginalFilename())
.contentType(multipartFile.getContentType())
.stream(multipartFile.getInputStream(), -1, 10485760).build());
inputStream.close();
System.out.println(test);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("文件上传失败");
}
}
}
配置文件
spring:
application:
name: imagebed
servlet:
multipart:
max-file-size: 2MB
max-request-size: 10MB
minio:
key: key
secret: secret
url: url
bucket_name: imagebed
你期待的结果是什么?实际看到的错误信息又是什么?
我期待的结果是程序能正常启动,实际看到的错误信息如下:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-19 10:38:40.522 ERROR 3816 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'uploadController' defined in file [D:\imagebed\target\classes\com\demo\imagebed\controller\UploadController.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.demo.imagebed.controller.UploadController]: Constructor threw exception; nested exception is java.lang.ExceptionInInitializerError
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1318) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1213) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
at com.demo.imagebed.ImagebedApplication.main(ImagebedApplication.java:10) ~[classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.demo.imagebed.controller.UploadController]: Constructor threw exception; nested exception is java.lang.ExceptionInInitializerError
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:217) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1310) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
... 18 common frames omitted
Caused by: java.lang.ExceptionInInitializerError: null
at com.demo.imagebed.controller.UploadController.<init>(UploadController.java:21) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:204) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
... 20 common frames omitted
Caused by: java.lang.IllegalArgumentException: endpoint must not be null.
at io.minio.MinioClient$Builder.validateNotNull(MinioClient.java:2741) ~[minio-8.2.1.jar:8.2.1]
at io.minio.MinioClient$Builder.validateNotEmptyString(MinioClient.java:2746) ~[minio-8.2.1.jar:8.2.1]
at io.minio.MinioClient$Builder.getBaseUrl(MinioClient.java:2790) ~[minio-8.2.1.jar:8.2.1]
at io.minio.MinioClient$Builder.endpoint(MinioClient.java:2803) ~[minio-8.2.1.jar:8.2.1]
at com.demo.imagebed.utils.MinioTool.<clinit>(MinioTool.java:40) ~[classes/:na]
... 26 common frames omitted
与目标 VM 断开连接, 地址为: ''127.0.0.1:13553',传输: '套接字''
进程已结束,退出代码为 1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
原因: 执行方法
MinioClient::Builder::endpoint
时URL
变量为null
根据 https://www.cnblogs.com/zemli... 所言:
因此在Spring尝试实例化
MinioTool
时, 会先执行以上静态语句, 而此时URL
,KEY
,SECRET
这些变量皆为null
, 又因为MinioClient::Builder::endpoint
方法有空值校验,所以抛出异常一般排错,
Caused by
语句是最重要的, 需要多关注.至于修改也很简单.
将静态调用更换为实例调用, 并取消
@Value
注解, 改为使用构造器初始化.不使用
@Value
的原因是@Value
注入晚于Bean实例化, 因此会依然抛如上异常,不过不用担心,
application.yml/application.properties
读取是早于Bean初始化的,参数可以通过
Environment
实例获取到.需要注意的是Spring的核心在于控制反转, 普遍情况下, 工具类使用静态字段和方法会比较方便, 但若是用到了框架相关, 如依赖注入, 属性注入等, 此时便需要和整体框架保持一致, 以方便操作.
检查下你的
endpoint
呢,你看你的嵌套异常的root cause提示:endpoint must not be null.
问题分析
问题出在这行代码
你这样写,是拿不到
Spring
注入的配置的,你也可以打断点验证原理解释
@Value
这个注解,确实是会根据application.yml
文件中的配置给MinioClient
注入值的,但是你使用的时候,并没有使用到Spring
的动态代理对象。解决方法
去掉
在
UploadController
中使用@Autowired
或者@Resource
直接通过Spring注入MinioClient
即可