今天在使用 IDEA 使用 MyBatis 的時候遇到了這種情況:
可以看到 userMapper 下有個紅色的波浪警告,雖然代碼沒有任何問題,能正常運行,但是這個紅色警告在這里杵着確實讓人很窩心。
於是我在網上找了找,最終明白了原因所在:
- 因為 IDEA 可以智能的理解上下文,然而 UserMapper 這個接口是 MyBatis 的 IDEA 理解不了。
- 而
@Autowired
注解,默認情況下要求依賴對象(也就是userMapper
)必須存在。而 IDEA 認為這個對象的實例/代理是個 null ,所以就友好地給個提示。
然后最終的解決方案總結了幾個,按需使用把:
方法1:為 @Autowired
注解設置 required = false
使用 @Autowired
注解時,若希望允許 null 值,可設置 required = false,像這樣:
1 @Autowired(required = false) 2 private UserMapper userMapper;
這樣就不會有警告了。原因很好理解:IDEA 認為 userMapper 是個 null ,給了警告;加上 required = false 后,使用 @Autowired
注解不再去校驗 userMapper 是否存在了。也就不會有警告了。
總結:
這種方式有點蛋疼。一個龐大的既有項目,可能到處都在引用 Mapper,總不能到處都補上 required = false 吧……而且對於新手/新員工,很難一眼看懂加 required = false 屬性只是為了解決 IDEA 的警告。
方法2:使用 @Resource 替換 @Autowired
像這樣:
@Resource private UserMapper userMapper;
這樣也不會再有討厭的警告。如果你對原因感興趣,不妨了解一下《@Autowired 與@Resource的區別》。
總結:
這種方式挺贊,但如果一個項目已經大量使用 @Autowired ,然后為了個警告到處改成 @Resource ,也有點蛋疼。
方法3:在 Mapper 接口上添加 @Repository 注解
@Repository public interface UserMapper extends Mapper<User> { }
這樣能讓你的
@Autowired private UserMapper userMapper;
不再報紅。
當然,如果你用 @Component 替換 @Repository 也是可以的。原理大致:IDEA 不是認為 userMapper
是個 null 嘛…加個 @Repository 注解騙一下 IDEA 就OK了……
總結:
這種方式比較贊,改動小,也簡單,我比較喜歡。
方法4:用 Lombok
@Service @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class TestService { private final UserMapper userMapper; ... }
但如果自己手寫成 Lombok 生成的代碼,IDEA依然會給你報警告 。我猜,應該是 IDEA 的 Lombok 插件把 IDEA 搞懵逼了…所以不提示了…
總結 :這是我目前最喜歡的方式。原因有2:
- Spring 官方並不建議直接在類的 field 上使用 @Autowired 注解,原因詳見:《Why field injection is evil》 ,用本方法可將 field 注入編程構造方法注入,Spring 是比較推薦的。
- 體現了 Lombok 的優勢,簡化了你的代碼。而且你也不用在每個 field 上都加上 @Autowired 注解了。
不過這種方式也有缺點:那就是如果你類之間的依賴關系比較復雜,特別是存在循環依賴(A引用B,B引用A,或者間接的循環引用)時,應用將會啟動不起來……這其實是構造方法注入方式的缺點。
方法5:把 IDEA 的警告關掉。
個人沒試過,也沒有動力去試。沒有提示的 IDEA 是沒有靈魂的,我從來不去修改 IDEA 的任何警告設置。
方法6:安裝 mybatis plugin 即可解決該問題。
總結:
以上是解決問題的6種方法。問題本身其實比較簡單,但其實隱藏的知識點其實挺多的,例如:
- @Autowired 和 @Resource 有什么區別。
- 為什么 Spring 不建議使用 field 方式注入。
- @Repository、@Componnt、@Controller、@Service 有什么區別。