@Resource是Java自帶的@interface類型,類似於Spring的@Autowired。但是兩者的注入方式有很大的區別。@Resource是通過name注入,@Autowired是通過type注入,這也是這次刨坑的主要原因。
場景還原
背景介紹
- 一個類SettingService加了@Service,name爲settingService(spring掃描自動命名機制-將類的首字母小寫當做name)
- 另一個類BallGameSettingService也加了@Service,name爲ballGameSettingService
代碼如下:
@Service
public class SettingService {
......
}
@Service
public class BallGameSettingService{
.......
}
導火線
以下注入將會出現異常:Error creating bean with name ‘ballGameSettingController’: Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named ‘settingService’ is expected to be of type ‘com.xxx.BallGameSettingService’ but was actually of type ‘com.xxx.SettingService…EnhancerBySpringCGLIB..e4ce4a19’
public class BallGameSettingController extends BaseController {
@Resource
private BallGameSettingService settingService;
......
}
將上面的代碼換成以下三種寫法都可以:
public class BallGameSettingController extends BaseController {
@Resource(name = "ballGameSettingService")
private BallGameSettingService settingService;
......
}
或者
public class BallGameSettingController extends BaseController {
@Resource
private BallGameSettingService ballGameSettingService;
......
}
或者
public class BallGameSettingController extends BaseController {
@Autowired
private BallGameSettingService settingService;
......
}
根本原因:@Resource是通過name注入,@Autowired是通過type注入
在使用@Resource時,如果沒有設置name,也就是 @Resource(name = “ballGameSettingService”) 時,會默認取變量名稱當做name。所以造成這次異常的原因:
- 我們環境中存在兩個@Service的bean,名字分別爲:settingService和ballGameSettingService,我們在通過以下代碼注入的時候,獲取到的是settingService(類型:SettingService),導致了類型出錯。
@Resource
private BallGameSettingService settingService;
- 以下兩種正確寫法的本質是一樣,就是獲取ballGameSettingService(類型:BallGameSettingService)
public class BallGameSettingController extends BaseController {
@Resource(name = "ballGameSettingService")
private BallGameSettingService settingService;
......
}
和
public class BallGameSettingController extends BaseController {
@Resource
private BallGameSettingService ballGameSettingService;
......
}
- 使用@Autowired的本質是通過BallGameSettingService類型去獲取