Spring中被放棄的@Autowired,你會用嗎?
注入方式一:屬性(字段)注入
在某個屬性(字段)上使用@Autowired注解時,Spring在創建該Bean的過程中,會根據字段的類型或名稱從Spring容器中查找到所匹配的Bean對象,并賦值給該熟悉。
@Service
public class UserService {
// 注入方式一:屬性注入
@Autowired
private RoleService roleService;
public void printRoleService() {
System.out.println(roleService);
}
}
注入方式二:Setter注入
在某個Setter方法上使用@Autowired注解時,Spring在創建該Bean的過程中,會來調用該Setter方法,并且如果Set方法有入參參數,那么Spring會格局入參參數信息,從Spring容器中找到所匹配的Bean對象賦值給該入參。我們通過再Setter方法中給屬性賦值,從而就達到了Setter方法注入的目的。
@Service
public class UserService {
private RoleService roleService;
public void printRoleService() {
System.out.println(roleService);
}
public RoleService getRoleService() {
return roleService;
}
// 注入方式二:Setter注入
@Autowired
public void setRoleService(RoleService roleService) {
this.roleService = roleService;
}
}
注意:@Autowired注解其實可以添加在任何一個普通方法上,不一定是Setter方法。
注入方式三:構造函數注入
當某個構造方法上使用@Autowired注解時,表示該Bean在創建時會使用這個構造方法來實例化得到一個對象,并且Spring會根據該構造函數的入參參數的類型和名字,從Spring容器中找到所匹配的Bean對象傳給該入參,通過在構造函數中給屬性賦值,從而就達到了構造函數注入的目的。
@Service
public class UserService {
private RoleService roleService;
// 注入方式三:構造函數注入
@Autowired
public UserService(RoleService roleService) {
this.roleService = roleService;
}
public void printRoleService() {
System.out.println(roleService);
}
}
注入方式四:參數注入
盡管@Autowired注解可以加在普通方法或構造方法的參數之前,但是Spring框架中大部分地方都忽略了這種情況下的@Autowired注解,僅僅在spring-test模塊中的對于JUnit Jupiter的支持中,支持了參數前添加@Autowired。
@SpringBootTest(classes = ConstructorAttributeMain.class)
class UserServiceTest {
@Test
void printRoleService(@Autowired UserService userService) {
userService.printRoleService();
}
}
required屬性釋義
- required=true:默認值,必須存在Bean,否則報錯
- required=false:若找不到Bean,則為空
@Service
public class UserService {
@Autowired(required = true)
private RoleService roleService;
@Autowired(required = false)
private MenuService menuService;
public void print() {
System.out.println("role: " + roleService); // print class
System.out.println("menu: " + menuService); // pint null
}
}
靜態屬性(字段)注入
靜態屬性(字段)或方法是不會進行依賴注入的。
@Service
public class UserService {
@Autowired
private static RoleService roleService;
public void printRole() {
System.out.println(roleService);
}
}
但是實際開發中,我們可能會遇到此問題。因此,有兩種方式解決此問題:
構造方法注入
@Service
public class UserService {
private static RoleService roleService;
// 解決靜態導入第一種方式:構造函數注入
@Autowired
public UserService(RoleService roleService) {
UserService.roleService = roleService;
}
public void printRole() {
System.out.println(roleService);
}
}
Setter方法注入
@Service
public class UserService {
private static RoleService roleService;
// 解決靜態導入第二種方式:Setter方法注入
@Autowired
public void setRoleService(RoleService roleService) {
UserService.roleService = roleService;
}
public void printRole() {
System.out.println(roleService);
}
}
小結
綜上所述,@Autowired有三種注入方式,分別為:字段(屬性)注入,構造函數注入和Setter方法注入。
另外,@Autowired參數注入,僅在單元測試才有意義;靜態字段(屬性)注入為空問題,需要結合構造函數或Setter方法注入。