Spring中@Autowired 注解的注入规则

Spring中@Autowired 注解的注入规则
默认根据类型,匹配不到则根据bean名字

1.声明一个service接口

public interface HelloService {
    void sayHello();
}

2.service接口的实现类,此时bean名字是 helloServiceImpl

@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("say hello impl");
    }
}

3.增加一个Controller,注入service

// 生成一个bean,名字为 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService helloService;
    
    public void hello() {
        helloService.sayHello();
    }
}

4.测试①:

public class AppTest {
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloController controller = (HelloController) context.getBean("helloController");
        controller.hello();
    }
}

结果如下
在这里插入图片描述
成功将Service层的实现类注入到Controller层中,可以把步骤3 代码修改一下

// 生成一个bean,名字为 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService abc;
    
    public void hello() {
        abc.sayHello();
    }
}

结果也是可以的,因为@Autowired 第一是按照类型去匹配的,此时IoC容器中HelloService 接口只有一个实现类,所以属性名字怎么写都没关系,都可以注入进去

测试②:增加一个实现类,此时bean名字是 newServiceImpl

@Service
public class NewHelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("new say hello impl");
    }
}

现在IoC容器中有两个 HelloService接口的实现类,继续运行测试方法,结果为

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
 Error creating bean with name 'helloController': 
 Unsatisfied dependency expressed through field 'abc'; 
 nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
  No qualifying bean of type 'com.convict.service.HelloService' available: 
  expected single matching bean but found 2: helloServiceImpl,newHelloServiceImpl

因为一个接口有多个实现,所以@Autowired 就按照属性名字去找,即找一个名字为 abc的bean注入,然而IoC容器不存在一个名字叫abc的 bean,因此报错,把属性名改为下面任意一种就可以匹配到了

// 生成一个bean,名字为 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService helloServiceImpl;
    
    @Autowired
    private HelloService newHelloServiceImpl;
    
    public void hello() {
        helloServiceImpl.sayHello();
        newHelloServiceImpl.sayHello();
    }
}

在这里插入图片描述
测试③:

那我就要把属性名叫 abc,同时有多个实现,而且还能注入,那么在声明组件的时候取个名字就好了,比如

@Service("abc")
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("say hello impl");
    }
}

然后Controller 注入的还是abc,结果注入成功

// 生成一个bean,名字为 helloController
@Controller
public class HelloController {
    @Autowired
    private HelloService abc;
    
    public void hello() {
        abc.sayHello();
    }
}

在这里插入图片描述
测试④:

属性名叫 abc,同时有多个实现,同时可以注入,且不在注解处声明bean 的名字,那么这时候使用新的注解@Qualifier 配合@Autowired 一起使用

// 生成一个bean,名字为 helloController
@Controller
public class HelloController {
    @Autowired
    @Qualifier("helloServiceImpl")
    private HelloService abc;
    
    public void hello() {
        abc.sayHello();
    }
}

在这里插入图片描述
@Qualifier是指定 一个bean的名字

总结:

1.一个接口只有一个实现的情况下,属性名字怎么写都无所谓,因为按照类型匹配就只有一个bean

2.一个接口多个实现的情况下:

① 属性名字跟组件名字一致,组件名字可以在声明的时候指定,比如 @Service(“abc”)

② 属性名字跟组件名字不一致,配合@Qualifier 注解指定组件名字

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值