一.@AutoWired
使用该注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称
写个普普通通的接口
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/login")
public String login(String name, String password) {
User userBean = userService.loginIn(name, password);
if (userBean != null) {
return "success";
} else {
return "error";
}
}
}
public interface UserService {
User loginIn(String name, String password);
}
@Service
public class UserServiceImpl implements UserService {
//将DAO注入Service层
@Resource
private UserMapper userMapper;
@Override
public User loginIn(String name, String password) {
return userMapper.getInfo(name, password);
}
}
Dao层略,只看controller与server层。
如上,使用AutoWired,从Spring容器中获取UserService实现类,注入该属性,byType-根据类型注入。
运行成功
然后根据这个说法,做个实验,既然是获取UserService这个接口的实现类,那么如果有多个UserService实现类呢,再创建一个实现类如下,
@Service
public class testServiceImpl implements UserService {
@Override
public User loginIn(String name, String password) {
return null;
}
}
然后我再次运行代码看看会报什么错?
然后代码运行,直接报错如下,匹配到了两个,找不到单个的来匹配。
Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.service.UserService' available: expected single matching bean but found 2: userServiceImpl,testServiceImpl
原因是如果有两个实现类,不管是service还是dao层的,如果都implements同一个接口,那么当使用AutoWired注入的时候需要另外指明要使用的是哪一个实现类。
改动如
@RestController
public class UserController {
@Autowired
@Qualifier("userServiceImpl") //指定bean名称,默认开头小写
private UserService userService;
@PostMapping("/login")
public String login(String name, String password) {
User userBean = userService.loginIn(name, password);
if (userBean != null) {
return "success";
} else {
return "error";
}
}
}
这里使用了Qualifier指定了我要使用UserServiceImpl这个实现类的bean名称,然后注意开头默认小写才能注入进来,否则代码报红。
然后启动正常运行,图略。
二.@Resource
继续复用上面的代码,将testServiceImpl注释掉,改成resource如下
@Resource
private UserService userService;
正常运行,图略。
现在将testServiceImpl放开呢?
答案是肯定的,与上面的报错提示一致。
匹配到了两个,找不到单个的来匹配。
所以解决如下,给实现类取个名字,比如:
@Service("userService")
public class UserServiceImpl implements UserService {
}
由于在controller层注入的名字叫做userService,
private UserService userService;
所以得给该实现类取个一样名字的,否则代码运行报错。所以这里可以看出该注解先根据名称注入。
再做个实验,如果就不想给实现类指定名字,可以在@Resource注解后面指定,如下
@Resource(name = "userServiceImpl")
private UserService userService;
这里的名字也就是实现类的名字,但是开头得小写,否则提示找不到。
还有一种type的指定方式,如下
@Resource(type = UserServiceImpl.class)
private UserService userService;
这两种方式都是为了定位到那一个具体的实现类,都能正常运行。
三.总结
byType:意思是根据实现类注入,如果有多个实现类,那么具体需要指定一个。
@AutoWired:
默认从Spring容器中获取UserService实现类,注入该属性,byType-根据类型注入;
如果Spring容器中有多个UserService实现类,会抛出异常;
可以使用@Qualifier("userServiceImpl"),指定需要的bean;
@Resouce
默认从Spring容器中获取名为userService的bean,注入该属性,byName-根据名称注入;
如果找不到名为userService的bean,接着会去找UserService的实现类,然后byType注入;
如果Spring容器中有多个UserService实现类,会抛出异常;