注入方式一:属性(字段)注入
在某个属性(字段)上使用@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方法注入。