spring boot @Autowired 自动注入为null问题解决

spring boot @Autowired 自动注入为null问题解决

    • 1.场景重现
    • 2.四种解决方案

1.场景重现

1.今天在做统一配置的时候,将所有的yml中的配置文件移到class类里面,并且用@Component注解注入到spring容器中管理,然后在其他类中用@Autowired注入进去,获取配置文件属性,这样做的好处是统一管理,不用在其他类中一个一个获取。如下图所示:

@Data
@Component
public class SystemYml {
    @Value("${electronsign.priKeyString}")
    private  String priKeyString;
    @Value("${electronsign.appId}")
    private  String appId;
    @Value("${electronsign.baseUrl}")
    private  String baseUrl;
    @Value("${electronsign.templateId}")
    private String templateId;
    @Value("${electronsign.notifyUrl}")
    private String notifyUrl;
    @Value("${electronsign.aygPublicKeyStr}")
    public String aygPublicKeyStr;
    @Value("${electronsign.notifyUrlIdCard}")
    private String notifyUrlIdCard;
    @Value("${electronsign.isPreview}")
    private String isPreview;
    @Value("${uploadFile.filePath}")
    private String saveImgFile;
}

spring boot @Autowired 自动注入为null问题解决_第1张图片

按道理来说,我们平常的用法都是可以注入的,但是此时我们注入的systemYml为null,导致获取属性的时候直接报空指针错误。

2.四种解决方案

1.首先看看注入失败的类有没有被spring包扫描到,不过这个一般都是没有问题的。在启动类中加入@ComponentScan注解扫描。
2.这个类没有托管给spring 管理,一般在类的上面添加@Component注解就行。
3.通过PostConstruct 注解,在初始化bean之前进行init方法,初始化完成以后,就可以获取到对象属性值。

@RestController
public class TestNull {
    @Autowired
    public   SystemYml systemYml;
    private TestNull testNull;
    @RequestMapping("/v1/inner/ttt")
    public  void test1() {
        System.out.println(systemYml.getAppId());
    }
//@PostConstruct 注解的方法在加载类的构造函数之后执行,也就是在加载了构造函数之后,执行init方法,实现初始化bean之前进行的操作
    @PostConstruct 
    public void init() {
        testNull = this;
        testNull.systemYml = this.systemYml;
    }
}

4.手动实现自动注入的效果:写个工具类实现ApplicationContextAware接口,这样在其他地方使用这个工具类,就可以获取到被管理bean对象的值。

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
 * @Author: Mr sheng.z
 * @Description: 实现了ApplicationContextAware ,这个类就可以获取到所有引用对象的bean
 * @Date: Create in 13:19 2020/6/30
 */
@Component
public final class ContextUtil 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);
    }
}

测试类:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @Author: Mr sheng.z
 * @Description:
 * @Date: Create in 13:07 2020/6/30
 */
@RestController
public class TestNull {
   //手动获取被spring管理的bean,根据bean的名称
    private    SystemYml systemYml= ContextUtil.getBean(SystemYml.class);
    @RequestMapping("/v1/inner/ttt")
    public  void test1() {
        System.out.println(systemYml.getAppId());
    }
}

你可能感兴趣的:(java)