天天看点

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

说明:

(1)在【Spring IoC容器与Bean管理21:使用注解方式实现Spring IoC二:组件类型注解(对象实例化);@Repository,@Service,@Controller,@Component;】中,仅仅介绍了实例化对象,但是没有涉及为对象的属性注入数据;本博客中介绍的【自动装配注解】,其目的就是实现对象的依赖注入;

(2)【自动装配注解】包括【按类型装配注解】和【按名称装配注解】;

(3)本篇博客主要介绍以【@Autowired】注解为例,介绍【自动装配注解】中的【按类型装配注解】的使用和缺点;

(3)本篇博客,沿用【Spring IoC容器与Bean管理21:使用注解方式实现Spring IoC二:组件类型注解(对象实例化);@Repository,@Service,@Controller,@Component;】中的代码s08;

目录

 一:自动装配注解简介

0.【按类型装配】注解和【按名称装配】注解简述:

1.【按类型装配】的注解:@Autowired和@Inject:

2.【按名称装配】的注解:@Named和@Resource:

 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

[email protected]注解用法:【在属性上使用@Autowired注解】和【在set方法上使用@Autowired注解】

策略一:在userDao属性上使用@Autowired注解

策略二:在setUserDao()方法上使用@Autowired注解

区别分析:

[email protected]注解用法:缺点和问题

(1)演示:为什么,在工作中,不推荐使用【按类型装配注解】;

(2)使用【按类型装配注解】,如何解决【由于IoC容器中出现多个相同类型的对象,从而导致的NoUniqueBeanDefinitionException】的问题?

 一:自动装配注解简介

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

0.【按类型装配】注解和【按名称装配】注解简述:

          ● 【按名称装配】:在【Spring IoC容器与Bean管理12:IoC在项目中的作用;】中的s04项目为例:
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

在绝大多数场景下,我们都是采用【按名称装配】的策略;

          ●【按类型装配】:不需要关心在IoC容器中,bean的名称是什么;在运行过程中为属性注入值时,只需要从IoC容器中获取对应类型的对象,然后完成自定注入;

1.【按类型装配】的注解:@Autowired和@Inject:

          ● @Autowired:这个是Spring提供的,即这是Spring自己提供的规范;

          ● @Inject:由JSR-330(Java规范要求第330号文件,这个文件是Java领域的标准和业界的规范)提供的标准;自然Spring对JSR-330也提供了支持;

           ● @Autowired和@Inject这两个【按类型装配】的注解,不推荐使用;更多的时候,鼓励使用【按名称装配】的注解;

2.【按名称装配】的注解:@Named和@Resource:

          ● @Named:这个注解要和@Inject注解匹配使用;即在@Inject注解后,增加@Named注解,其会按照属性名(或者其他自定义的规则)完成对象的装配;同时@Named也是JSR-330(Java规范要求第330号文件,这个文件是Java领域的标准和业界的规范)提供的标准

          ● @Resource:这个注解出现的较早,是JSR-250提供的标准;这个注解不但可以按照名称进行依赖注入,如果不满足按名称进行依赖注入时,其也能自动按类型装配;@Resource这个注解是目前功能最强大的自动供装配注解;

 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

          ● 沿用【Spring IoC容器与Bean管理21:使用注解方式实现Spring IoC二:组件类型注解(对象实例化);@Repository,@Service,@Controller,@Component;】中的代码s08;

          ● 在实际工作中,不推荐使用【按类型装配】注解;

          ● 事先说明:MVC架构模式采用分层的方式依次的逐级调用的,即Controller调用Service(也就是Controller依赖于Service啦),Service调用Dao(也就是Service依赖于Dao);由于前面,我们在UserController类、UserService类、UserDao类中使用了对应的注解,所以在IoC容器初始化的时候,这三个类的bean对象就会被创建了;

1.@Autowired注解用法:【在属性上使用@Autowired注解】和【在set方法上使用@Autowired注解】

策略一:在userDao属性上使用@Autowired注解

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
运行:
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

通过运行结果,可以看到上面实现了对象注入,但是其并不是通过setter方法来实现的;

但是,如果采用下面的策略:

……………………………………………………

策略二:在setUserDao()方法上使用@Autowired注解

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
重新运行:
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
…………………………………………………… 

区别分析:

(1)【在属性上使用@Autowired注解】和【在set方法上使用@Autowired注解】,都可以完成对象的注入;

(2)【在属性上使用@Autowired注解】没有执行set方法;【在set方法上使用@Autowired注解】执行了set方法;

(3)如果装配注解放在set方法上,则自动按类型或者名称对set方法参数进行注入;

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
(4)如果装配注解放在属性上,IoC容器会自动通过反射技术,将属性private修饰符自动更改为public,由于属性的访问修饰符成了public,这就意味着从外侧可以直接对这个属性赋值,不再执行set方法,然后赋值完成后,再将修饰符改回到private;(这个过程是在运行时,动态完成的,对程序员不可见)
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
(5)由于(4)中的原因,在实际开发中,如果使用注解来实现对象依赖注入的话,通常是不用写set方法的;
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

2.@Autowired注解用法:缺点和问题

(1)演示:为什么,在工作中,不推荐使用【按类型装配注解】;

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
既然有了Dao接口,那么UserDao类应该实现这个接口(在实际开发中,这也是约定俗成的开发方式):
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
因为有了所有Dao的接口,那么在Service中,按照面向对象编程的理念,userDao属性的类型也应该修改为IUserDao接口:
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

至此,还没有什么问题。

然后,比如原有的UserDao是基于Mysql数据库写的,如果后面需要改为Oracle数据库,直接的想法是新创建一个类,这个类实现IUserDao接口,然后按照Oracle开发就行了;

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
但是,这样以后就会出问题了:运行SpringApplication类,就会报错了:NoUniqueBeanDefinitionException:
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
该行报错信息完整摘录如下:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.imooc.spring.ioc.dao.IUserDao' available: expected single matching bean but found 2: udao,userOracleDao
           

其大意是,我期望在容器只有唯一的、匹配的bean,但是在容器中发现了两个bean(分别是userDao和userOracleDao);

之所以会注入失败,就是因为@Autowired注解是【按类型装配】的注解;

Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

(2)使用【按类型装配注解】,如何解决【由于IoC容器中出现多个相同类型的对象,从而导致的NoUniqueBeanDefinitionException】的问题?

解决办法1:去掉被抛弃的那个Dao类的@Repository注解;(目的是,IoC容器中不要出现类型重复的Dao对象)
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
解决办法2:引入@Primary注解
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解
运行结果:
Spring IoC容器与Bean管理22:使用注解方式实现Spring IoC三:自动装配注解(对象依赖注入);自动装配注解之【按类型装配注解】(@Autowired)的使用和缺点; 一:自动装配注解简介 二:自动装配注解:之【按类型装配】注解:之@Autowired注解

【按类型装配】注解之所以容易出问题的原因就是:在容器中,可能会出现多个相同类型的对象,如果稍不注意就会出现NoUniqueBeanDefinitionException;为了避免这个问题,在实际开发中,多使用【按名称装配】的注解,因为名称在容器中都是唯一的,所以可以有效避免刚才错误的发生;而【按名称装配】的注解在下篇博客中会给予介绍;

继续阅读