关于spring @Autowired注入启动过程中不为null,调用对象时为null的问题

如标题名称,其实这篇文章要讲的这个问题跟@Autowired没有太大关系,最终导致该问题的是CGLIB代理,之所以起名该标题,是因为我当时也始终以为该问题是@Autowired注入机制导致的。。。话不多说,直接上代码,情景如下:
IndexController类中有一段代码:

@RestController
public class IndexController {
	@Autowired
	private UserService userService;

	@RequestMapping("/doSignin")
	public String doSignin(SigninCommand signinCommand) {
			boolean hasMatch = userService.hasMatchUsername(signinCommand.getUsername());
	}
}

UserServiceImpl类中有一段代码:

@Component
public class UserServiceImpl implements UserService {
	@Autowired
	private HcUserDao hcUserDao;

	@Override
	public boolean hasMatchUser(String username, String password) {
		int matchCount = hcUserDao.getMatchCount(username, password);
		return matchCount > 0;
	}
}

HcUserDao类中有一段代码:

@Repository
public class HcUserDao extends BaseDao {
	private final static String MATCHUSERNAME_COUNT_SQL = "SELECT COUNT(*) FROM t_user WHERE username=?";
	
	public final int getMatchUsernameCount(String username) {
		return jdbcTemplate.queryForObject(MATCHUSERNAME_COUNT_SQL, new Object[] { username }, Integer.class);
	}
}

public class BaseDao {
	@Autowired
	protected EntityManagerFactory entityManagerFactory;
	
	@Autowired
	protected JdbcTemplate jdbcTemplate;
}

然后经过调试,在SpringBoot启动过程中,HcUserDao 中能看到jdbcTemplate对象已经注入成功,而到了UserServiceImpl 中,能看到hcUserDao对象注入成功,但是看jdbcTemplate字段,却是为null。程序调用过程中,也会抛出如下错误:

java.lang.NullPointerException
	at org.wongws.hichat.dao.HcUserDao.getmatchUsernameCount(HcUserDao.java:16)
	at org.wongws.hichat.service.UserServiceImpl.hasMatchUsername(UserServiceImpl.java:27)
	at org.wongws.hichat.controller.IndexController.doSignin(IndexController.java:17)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	......

中间经过一大堆波折,最后锁定到如下图的对象中:

在这里插入图片描述
看此处会发现hcUserDao是通过CGLIB动态代理生成的,而在target中能看到jdbcTemplate其实是有值的。
OK。既然到这里,问题其实已经转向到CGLIB上了。其实CGLIB在动态代理的时候,是没有对target原样照搬的,属性值会没有设置,这里也就能解释得通为什么jdbcTemplate为null,如果要得到的话,可以通过getJdbcTemplate()方法取值。
至于CGLIB的原理,大家也可以看看其他博文了解下。
这里附上如下文章 如何为spring代理类设置属性值 供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值