解决自定义类使用@Autowired注解注入失败的问题

问题描述

在工作中想要实现在工具类中通过@Autowired注入持久层的Mapper类,然而代码运行后发现报了空指针异常,即@Autowired注解注入失败了。
要怎样实现在我们自定义的工具类中完成依赖注入呢,先看一下可以完成注入的代码:

@Component
public class TestUtil{
	@Autowired
	private TestMapper testMapper;

	private static TestUtil testUtil;

	@PostConstruct
    public void init() {  
        testUtil = this;  
    } 

	public void test(){
		testUtil.testMapper.getValue();
	}
}
需要注意的地方

上面这段代码有以下几点需要注意:
1.首先要在类的最上方加上@Component或@Service注解,这样是为了让该类处于spring的管理之下,这样使用@Autowired注入才有可能成功。
2.之后我们声明了一个静态的TestUtil变量,细心的朋友可能发现了,TestUtil就是我们当前类本身,之后我们使用@PostConstruct注解,在方法中将当前的对象this赋值给了静态变量testUtil。之后我们需要使用到注入进来的testMapper对象时,需要利用到这个静态变量进行调用。即:
testUtil.testMapper.getValue();

为什么要使用@PostContruct注解

这里就需要知道被@PostContruct注解修饰的方法在何时执行。首先我们通过打印输出来看一下,什么时候会构造对象,什么时候会调用被该注解修饰的方法。上一下打桩过的代码:

@Component
public class TestUtil{
	@Autowired
	private TestMapper testMapper;

	private static TestUtil testUtil;
		
	public TestUtil(){
		System.err.println("构造函数");
	}
	
	@PostConstruct
    public void init() {  
        testUtil = this;
        System.err.println("post:"+testUtil);
    } 

	public void test(){
		System.err.println("method:"+this);
		testUtil.testMapper.getValue();
	}
}

可以看到我们在构造函数,@PostConstruct修饰的方法,和要被执行的test方法里都做了打印输出。
首先启动项目,查看springboot启动时打印情况如下图所示:
在这里插入图片描述
首先执行了构造函数,然后执行了@PostConstruct修饰的方法(由打印的内容post开头看出),将当前对象赋值给了本类类型的静态变量。
之后我们执行调用test方法的代码:
在这里插入图片描述
可以看到,在执行test方法时,只调用了构造函数,和我们test方法中的打印(由method开头可看出)。

为什么会产生这样的结果呢?

首先我们捋顺一下。
第一张图的打印结果很好理解,因为类上加了@Component注解,所以这个对象要被spring管理,因此在项目启动的时候,我们会构造这个对象。之后执行了被@PostConstruct修饰的方法,可以理解为这个方法是在依赖注入成功后执行的,在方法中我们将这个被spring管理的,依赖注入成功的对象赋值给了静态变量。
第二张图是我们在项目中new了一个工具类,所以肯定会执行一次构造函数,之后被@PostConstruct修饰的方法并没有执行,因此最开始推测他是一个spring的注解,但看过后发现他是一个java的注解,因为它是由servlet控制的,只在项目启动时执行一次,所以我们利用了这个特性来实现我们的需求。因为只在项目启动时执行,所以在我们new的这个工具类对象里自然就不会执行了。之后我们在test打桩,可以发现当前的this对象和被spring管理的对象并不是一个对象。这也很好理解,一个是spring管理的单例对象,一个是我们自己new的对象,当然是完全不同的两个对象。说到这儿可能很多朋友已经明白为什么通过静态变量来调用@Autowired注入的mapper是可以成功的了,原因是静态变量保存的这个对象是spring管理的对象,而我们new的这个对象是完全没有进行过依赖注入的,自然也就无法使用mapper啦。

结论

我们通过静态变量保存了一份spring管理的单例对象,来实现调用@Autowired注入的mapper对象。
没有被spring管理的对象,即自己new的一个对象,是无论如何都不会通过@Autowired注入成功的。

鸣谢

帅逼阿浩,指出了我之前存在的错误,特此感谢!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值