@Autowired 注解属于 org.springframework.beans.factory. annotation 包,可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
@Service 注解属于 org.springframework.stereotype 包,会将标注类自动注册到 Spring 容器中。
在一个类上面标注@Service或者@Controller或@Component或@Repository注解后,容器启动时,Spring组件扫描时就会发现它,并且会直接将其创建好变成Spring应用上下文中bean。
在需要使用时通过@Autowired注解把容器创建好的bean从容器获取过来赋予给使用类的成员属性
@Autowired注解的注入规则
默认根据类型,存在多个时则根据名字进行匹配
1.定义一个user的service接口
public interface User {
void hello();
}
2.创建一个user的service接口的实现类
@Service
public class Userimpl implements User{
@Override
public void hello(){
System.out.println("hello");
}
}
3.增加一个Controller,注入user的service
@Controller
public class HelloController {
@Autowired
private User user;
public void hello(){
user.hello();
}
}
4.在测试类中运行
@SpringBootTest
class SbPack2ApplicationTests {
private HelloController helloController;
@Autowired
public SbPack2ApplicationTests (HelloController helloController)
{
this.helloController=helloController;
}
@Test
void contextLoads() {
helloController.hello();
}
}
成功输出了hello
但是如果user接口有两个实现类比如说再增加如下一个实现类
@Service
public class NewUserimpl implements User{
@Override
public void hello(){
System.out.println("hello");
}
}
那么Controller里面就会出现报错,此时IoC容器中HelloService 接口存在两个实现类,自动装配决定不了使用哪一个实现类,会像下图一样报错
这时候就需要用到一个新的注解
@Qualifier是指定 一个bean的名字
作用就是解决当使用@Autowired遇到多个实现类时的问题
现在我们可以尝试
@Controller
public class HelloController {
@Qualifier("newUserimpl") //这里并不是和实现类名完全相同,应该有自己的命名规则
@Autowired
private User newuser;
@Qualifier("userimpl")
@Autowired
private User user;
public void hello(){
user.hello();
newuser.hello();
}
}
输出结果如下
又或者当出现多个实现类时我们还可以这样做,在service注解处直接标明限定符
@Service("abs")
public class Userimpl implements User{
@Override
public void hello(){
System.out.println("hello");
}
}
@Service("abd")
public class NewUserimpl implements User{
@Override
public void hello(){
System.out.println("new hello");
}
}
那么在Controller中使用时就可以不用加上@Qualifier注解
而是让属性名直接就是限定符
@Controller
public class HelloController {
@Autowired
private User abs;
@Autowired
private User abd;
public void hello(){
abs.hello();
abd.hello();
}
}
同样也能正常输出
但是当我们需要用同一个实现类创建两个属性时就需要属性名不同而且还要用到 @Qualifier
Controller中就变成
@Controller
public class HelloController {
@Autowired
private User abs;
@Autowired
private User abd;
@Qualifier("abd")
@Autowired
private User abd1;
public void hello(){
abs.hello();
abd.hello();
abd1.hello();
}
}
输出变成
上面提到的添加了@Service的实现类会在扫描进入IOC容器变成一个bean时就如下图所示
当在其中一个实现类中加上一个无参构造函数,不论下面有没有使用@Autowired进行注入都会执行一遍
@Service("abs")
public class Userimpl implements User{
public Userimpl(){
System.out.println("hello user");
}
@Override
public void hello(){
System.out.println("hello");
}
}
可以看见构造参数的输出是最先出现的