关于springboot读取配置类,使用@Autowired自动注入为null的问题

news2025/7/19 6:21:36

问题

之前写了一个配置类,读取config.yml配置文件里写好的阿里云oss的一些参数配置。配置类读取并无问题,但是在另一个普通类里自动注入该配置类时,引用配置类属性却报NullPointer异常。然后终于发现问题原因了。

代码

1. 配置文件

application-oss.properties

aliyun.oss.endpoint=oss-ap-southeast-1.aliyuncs.com
aliyun.oss.bucket-name=tms-oss-singapore
aliyun.oss.key-id=LTAI5tN999G8YVxnJ8ss8ouh
aliyun.oss.key-secret=dSk4kGrtHFT2quUBwO4KNJFcQLwFZc

2. 配置类

package com.yunsystem.common.utils;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;


@Component
@Data
@PropertySource(value = {"classpath:application-oss.properties"})
@SpringBootApplication
public class OssProperties {

    @Value(value = "${aliyun.oss.endpoint}")
    private String endpoint; // bucket所在地域对应的endpoint
    @Value(value = "${aliyun.oss.key-id}")
    private String keyid; // accesskey的id
    @Value(value = "${aliyun.oss.key-secret}")
    private String keysecret; // accesskey的密钥
    @Value(value = "${aliyun.oss.bucket-name}")
    private String bucketname; // 存储桶名称

}

3. 调用配置类的普通类

以下类为OSS上传文件类

package com.yunsystem.common.utils;

import com.aliyun.oss.*;
import com.aliyun.oss.model.ObjectMetadata;
import com.yunsystem.common.error.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class OssUpload {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private OssProperties ossProperties;    // 这里即注解自动装配

    /**
     * 使用aliyun-sdk实现上传
     * @param inputStream 上传的文件流
     * @param module   oss目录
     * @param originalFileName 文件名
     * @return
     * @throws BusinessException
     */
    public Map upload(InputStream inputStream, String module, String originalFileName) throws BusinessException {

        /**
         * 获取oss的属性
         */

        String endpoint = ossProperties.getEndpoint();
        String accessKeyId = ossProperties.getKeyid();
        String accessKeySecret = ossProperties.getKeysecret();
        String bucketName = ossProperties.getBucketname();
        String objectName = "";
        Map<String, String> map = new HashMap<>();

        // 创建上传文件的元信息,可以通过文件元信息设置HTTP header。
        ObjectMetadata meta = new ObjectMetadata();
        // 创建OSSClient实例。
        OSS ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String folder = simpleDateFormat.format(new Date());
            // 文件名  sn+开始结束时间戳
            String fileName = originalFileName.substring(0, originalFileName.lastIndexOf(".")); //UUID.randomUUID().toString();

            //文件扩展名
            String fileExtention = originalFileName.substring(originalFileName.lastIndexOf("."));
            if (StringUtils.isNotEmpty(module)) {
                //最终的路径 类似actionRec/abnormal/2023-01-05-09:52:41/xxxxxxxxx.jpg
                objectName = module + "/" + folder + "/" + fileName + fileExtention;
            } else {
                objectName = folder + "/" + fileName + fileExtention;
            }
            meta.setContentType("text/plain");
            meta.setContentDisposition("inline");

            // 上传文件
            ossClient.putObject(bucketName, objectName, inputStream, meta); // bucket名称,上传文件路径和名称,上传文件输入流
            //https://rxt.oss-cn-beijing.aliyuncs.com/avatar/01.jpeg
            map.put("fileUrl", "https://" + bucketName + "." + endpoint + "/" + objectName);
            return map;

        } catch (OSSException oe) {
            logger.error("Error Message: " + oe.getErrorMessage());
            throw new ServiceException(oe.getMessage());
        } catch (ClientException ce) {
            logger.error("Error Message: " + ce.getMessage());
            throw new ServiceException(ce.getMessage());
        } finally {
            if (ossClient != null) {
                // 关闭OSSClient。
                ossClient.shutdown();
            }
        }
    }
}

4. 业务类ServiceImpl调用oss上传工具类实现业务文件上传

@Transactional
@Service
public class DeviceActiveInfoImpl implements DeviceActiveInfoService {
	
	...
	public void uploadFile(MultipartFile file) {
		...
		// 1. 解析文件数据
        String fileName = file.getOriginalFilename();
        File newFile = new File(fileName);
        try {
            FileUtils.copyInputStreamToFile(file.getInputStream(), newFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        newFile.deleteOnExit();  // 删除临时文件

        // 2. 调用上传文件接口
        OssUpload ossUpload = new OssUpload();    //  !!! 注意这里,问题在这!!!
        // 2.1. 上传文件
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();  // 获取文件流
        } catch (IOException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String extName = fileName.substring(fileName.lastIndexOf(".")); // 后缀名
        //fileName = sn + sdf.format(startTimeStamp) + extName;
        String module = "ScanKMS/error";  // 存储空间目录文件夹

        Map map = ossUpload.upload(inputStream, module, fileName);
        // 2. 保存记录到数据库
        String filePath = (String) map.get("fileUrl");

        for (DeviceActiveInfo deviceActiveInfo : deviceActiveInfos) {
            deviceActiveInfo.setFile_url(filePath);
            deviceActiveInfoMapper.updateByPrimaryKeySelective(deviceActiveInfo);
        }
	}
}

原因

读取配置没问题,但是在普通类@Autowired注入失败,原因是 我的普通类是oss上传工具类,然后在业务类方法中调用时使用了new 的方式!!!

// 2. 调用上传文件接口
        OssUpload ossUpload = new OssUpload(); 

解决

业务类业务方法调用oss上传工具类时, 同样使用 @Autowired 自动注入的方式注入而不是new的方式!!!

	@Autowired
    private OssUpload ossUpload;

—— 以下引用自:风兮雨露——:

1、描述

有时候我们在某个类用@Autowired 进行注入时,会发现注入参数为null,这时候会有疑惑。

可能存在的原因:

(1)该类没有托管给spring 管理,一般在类的上面添加@Component

(2)你的这个类有被new出来的实例的,new 过的对象不会交给Spring容器管理 所以里面的 service或者dao注入不进来。一般是指引用某些框架,你是继承某个接口,但是这些框架默认new过这个方法,比如MVC拦截的HandlerInterceptor类。

2、解决方式

对于(1)其实就加入@Component 就可以了。接下来讲怎么解决第(2)种情况:

有时候你确实需要在这个new 的类去注入某些类,但是用@Autowired 又注入为null,这时候我们需要手动去弄Spring容器中的Bean实现ApplicationContextAware接口。

(1)比如我想在某个类实现RedisUtils 类的注入,但是用@autowired 会报null

(2)这时候我们就要手动实现这个功能,写个BeanUtils 类 实现ApplicationContextAware接口

 
 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
 
@Component
public class BeanUtils implements ApplicationContextAware  {
    protected static ApplicationContext applicationContext ;
 
    @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        if (applicationContext == null) {
            applicationContext = arg0;
        }
 
    }
    public static Object getBean(String name) {
        //name表示其他要注入的注解name名
        return applicationContext.getBean(name);
    }
 
    /**
     * 拿到ApplicationContext对象实例后就可以手动获取Bean的注入实例对象
     */
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}

注意,该类必须用@Component 注解

(3)使用时用以下方式

    /**
     * 由于不能用@Autowired进行注入,则使用这种手动注入方式
     */
    private RedisUtils redisUtils = BeanUtils.getBean(RedisUtils.class);

这样就要正常引用redisUtils ,这样手动出来的跟@Autowire 一样的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/347285.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GeoTools:Shapefile创建

在上一篇文章《GeoTools&#xff1a;Feature&Shapefile之CRUD操作》中&#xff0c;介绍了基于GeoTools的Shapefile文件CRUD基本操作&#xff0c;那么&#xff0c;能否使用GeoTools创建Shapefile文件呢&#xff1f;答案是可以的。以下&#xff0c;我们将深入讨论如何实现。 …

零基础机器学习做游戏辅助第十二课--原神自动钓鱼(二)

一、模拟训练环境 上节课我们已经能够判断人物的钓鱼状态,接下来我们就需要对鱼儿上钩后的那个受力框进行DQN训练。 方案有两个: 使用卷积神经网络直接输入图像对网络进行训练。使用普通网络,自己写代码模拟出图像中三个点的动态并把值给神经网络进行训练。这里我们选用第二…

IB数学课程有哪些异同?如何选课?

自从IBDP在2019年进行数学课程改革后&#xff0c;许多IB小伙伴们就不知该如何选课了……改革后的IB数学课程包括4门课程&#xff0c;也就是&#xff1a;● Mathematics: analysis and approaches SL & HL (first assessment 2021)● Mathematics: applications and interpr…

科技云报道:“吞金兽”ChatGPT背后:AI算力告急!

科技云报道原创。 近两个月来&#xff0c;全世界的网友们都在兴致勃勃的“调教”ChatGPT&#xff0c;但第一个受不了的却是ChatGPT的所有者。 为了更长远的发展&#xff0c;OpenAI宣布了付费订阅版ChatGPT Plus&#xff0c;每月收费20美元。 虽然OpenAI表示&#xff0c;将持…

Monorepo or 物料市场?结合工作实际情况对公司现有前端体系的思考

前言 去年年中基于若依vue前端框架进行了改造&#xff0c;加上后端的配合&#xff0c;我写了一套脚手架和项目中后台模板。中后台模板中包含了许多基础代码&#xff0c;比如登录/注册、路由、权限等等相关功能。这个中后台模板是基于我们实际开发定制的&#xff0c;所以跟通用…

SpringBoot——配置文件

项目中有许多公共使用的变量&#xff0c;例如端口号&#xff0c;连接数据库的配置&#xff0c;还有我们自己创建的变量&#xff0c;这些可以放到SpringBoot的配置文件中统一调配使用 properties 基本语法格式&#xff1a; keyvalue例如配置项目的端口号为8888&#xff1a; …

Bean注入到Spring方式

扒一扒Bean注入到Spring的那些姿势 配置文件的方式就是以外部化的配置方式来声明Spring Bean&#xff0c;在Spring容器启动时指定配置文件。配置文件方式现在用的不多了&#xff0c;但是为了文章的完整性和连续性&#xff0c;这里我还是列出来了&#xff0c;知道的小伙伴可以自…

Jetson Xavier NX设备将opencv和tensorrt链接到conda环境

注意安装的时候先查看设备旧版本的opencv&#xff0c;卸载干净后再装。 Jetpack4.6 opencv4.1.1 conda安装 过程翻一下之前的博客把&#xff0c;下面是创建环境开始 conda create -n py36 python3.6.9 OPENCV_EXTRA_MODULES_PATH/home/ta/open/opencv_contrib-4.1.1/modul…

白银走势图如何做空?

做现货白银的好处是&#xff0c;我们可以在白银走势图上做空&#xff0c;不再像股票那样只能先卖后买&#xff0c;还能先卖后买&#xff0c;这样我们做投资就多了一份从容&#xff01;任何时候我们都能获得投资获利的机会&#xff0c;但是由于习惯了单向交易&#xff0c;我们要…

Sarsa算法讲解及实现

Sarsa算法讲解及实现 1. Q表格 我们使用表格来存储每一个状态 state, 和在这个 state 每个行为 action 所拥有的 Q 值。 Q即为Q&#xff08;s,a&#xff09;就是在某一时刻的 s 状态下(s∈S)&#xff0c;采取动作a (a∈A)动作能够获得收益的期望&#xff0c;环境会根据agent…

java嵌入式持久化消息队列SMQ,改造自FQueue

一、说明之前项目中一直使用ConcurrentLinkedQueue做为缓冲队列&#xff08;主要是单个项目内&#xff0c;单条改批量的场景&#xff0c;多个项目间使用的是rocketmq&#xff09;&#xff0c;虽然用着方便但是是纯内存的&#xff0c;如果项目发生异常崩溃内存队列中的数据就会全…

JavaSE学习day6 进制转换和idea的调试

1.进制 1.1 常见的进制分类(掌握) 学过计算机组成原理的同学可以跳过这里。 二进制 十进制 八进制 十六进制 1.2 二进制 计算机数据在底层存储和运算的时候&#xff0c;都是以二进制的形式操作的&#xff0c;了解不同的进制&#xff0c;便于我们对数据的运算过程理解的更…

个人博客推出了更多功能

背景 Web2.0的典型代表博客&#xff0c;吸引着粉丝们打造属于自己的个人博客&#xff0c;分享自己的学习经验&#xff0c;记录自己的日常生活。随着大厂的入局&#xff0c;我们可以很容易的申请自己的个人博客&#xff0c;但是弊端就是往往会被他们控制&#xff0c;甚至封号。…

汕头市农村生活污水治理“十四五”规划行动方案

汕头&#xff0c;简称“汕”&#xff0c;广东省辖地级市&#xff0c;北接潮州&#xff0c;西邻揭阳&#xff0c;南濒南海&#xff0c;东与台湾隔海相望&#xff0c;境内韩江、榕江、练江三江入海&#xff0c;是中国大陆唯一拥有内海湾的城市。今天就来为大家介绍&#xff0c;汕…

Windows系统实现命令行(CMD)关闭指定的IIS网站

一、需求说明我们部署在Windows服务器上的IIS网站&#xff0c;需要在特定的时间停止一会后在进行重新启动该网站。二、思路分析由于需要特定的时间停止后重启网站&#xff0c;则手动操作肯定是不行的&#xff0c;需要实现自动化操作&#xff1a;①特定时间操作可以使用Windows系…

聚观早报|王慧文要做「中国版 OpenAI」;Temu斥资近亿元赞助超级碗

点击蓝字 / 关注我们今日要闻&#xff1a;王慧文要做「中国版 OpenAI」&#xff1b;Temu斥资近亿元赞助超级碗&#xff1b;新东方在线股价收跌2.8%&#xff1b;ChatGPT带动的AIGC创业热潮要来了&#xff1b;传谷歌拆分其AR部门王慧文要做「中国版 OpenAI」 2 月 13 日&#xff…

CSS中的常见单位(px,%,em,rem,vw,vh,vmax,vmin,calc)

像素(px)&百分比(%) 像素(Pixel) 长度单位&#xff0c;相对于显示器屏幕分辨率而言&#xff0c;通常在不定义显示缩放比例的情况下&#xff0c;1px对应显示器屏幕上的一个像素点。早年的pc端展示的页面基本都用这个单位。 百分比(%) 相对长度单位&#xff0c;指占用的父…

电源模块 DC-DC直流升压正负高压输出12v24v转±110V±150V±220V±250V±300V±600V

特点效率高达80%以上1*2英寸标准封装电源正负双输出稳压输出工作温度: -40℃~85℃阻燃封装&#xff0c;满足UL94-V0 要求温度特性好可直接焊在PCB 上应用HRA 1~40W系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&#xff1a;4.5~9V、9~18V、及18~36VDC标准&…

对比Hashtable、HashMap、TreeMap有什么不同?

第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同&#xff1f; Map 是广义 Java 集合框架中的另外一部分&#xff0c;HashMap 作为框架中使用频率最高的类型之一&#xff0c;它本身以及相关类型自然也是面试考察的热点。 今天我要问你的问题是&#xff0c;对比 Hashtable、…

HTTP协议——详细讲解

目录 一、HTTP协议 1.http 2.url url的组成&#xff1a; url的保留字符&#xff1a; 3.http协议格式​编辑 ①http request ②http response 4.对request做出响应 5.GET与POST方法 ①GET ②POST 7.HTTP常见Header ①Content-Type:: 数据类型(text/html等)在上文…