目录
1.第一个Spring项目
2.存储Bean对象
2.1 准备工作
2.2 五大类注解
2.3 方法注解@Bean
2.4 Bean对象的默认命名规则
3. 读取Bean对象
3.1 属性注入
3.2 setter注入
3.3 构造方法注入
3.4 注入异常问题
3.5 注入方式优缺点
3.6 @Autowired和@Resource的区别
1.第一个Spring项目
在学习更简单的方式来读取和存储Bean对象之前,我们先来回忆一下之前Spring项目的创建以及在Spring-core项目中我们是如何创建和存储对象的。
上面的这种Spring对象的存储和读取方式虽然能够满足我们的需求,但是这也只是站在小项目的层面上来讲的。如果一个项目中的类多起来了,我们如果采用上面这种面向xml配置配置Spring存储Bean对象,那得在spring的配置文件中添加多少bean标签,并且id还不能够重复!所以这种操作Spring存储和读取Bean对象的做法太过复杂,接下来我们来看如何更简单的实现spring存储Bean对象以及从Spring中读取Bean对象的操作。
2.存储Bean对象
2.1 准备工作
在使用注解来配置Spring存储对象时,需要先在spring配置文件中添加上以下的内容:
2.2 五大类注解
配置Bean对象被Spring识别的注解有以下五个,都能够实现被spring识别并将该Bean对象加载到容器中:
- @Controller(控制器存储)
- @Service(服务存储)
- @Repository(仓库存储)
- @Component(组建存储)
- @Configuration(配置存储)
为什么要有这么多的类注解?
这就与每个省市都有自己限定名称的车牌号一样,不仅能够节约号码,同时让别人看到能够大致清楚这是哪里的车牌号。我们的类注解也是这样,在项目开发中,一个项目中可能有特别多的类,并且不同的类可能归属于不同的层级,我们这几种类注解就是让程序员看到之后,能够直接了解该类的用途层级。如下图所示:
更详细一点:
- @Controller——控制器存储
存储逻辑控制层的Bean对象。归属于程序的逻辑控制层。前端发送的数据通常会先经过逻辑控制层的控制器来判断传递的参数是否合法- @Service——服务存储
存储服务层的Bean对象。归属于程序的服务层。前端数据在经过控制器校验合法后将数据传递到服务层,而一个客户服务可能需要操控多张表,我们的服务层就负责调度底层的数据存储层逻辑来进行对应请求服务的处理。- @Repository——仓库存储
存储数据处理层的Bean对象。归属于持久层。通常情况下每一个表都会对应一个@Repository对象。该对象位于数据处理层,接受服务层的调度,完成对应的业务处理逻辑中涉及到的数据操作,这一层将直接与数据库打交道- @Component——组件存储
存储具有通用性质的工具类对象,归属于公共工具类,这些工具类提供了一些公共方法。- @Configuration——配置存储
归属于配置层,用来配置当前项目中的一些信息
2.3 方法注解@Bean
首先需要注意的是,方法注解@Bean需要与五大类注解一起搭配使用。通过@Bean可以获得该标注方法执行结束后返回的Bean对象。如下图:
2.4 Bean对象的默认命名规则
通过之前的学习我们知道,存储到Spring中的Bean对象要有一个唯一标识身份的Id信息,所以我们之后才能正确的获取到这个Bean对象。那么,我们在使用五大类注解时并不能指定这个id信息,这说明Spring是帮助我们来完成了这件事的。那么,Spring是按照哪种规则来命名的呢?为我们一起来翻看下源码:
可以看到,当我们使用五大类注解时,Spring其实是将根据类的名称来进行这个类的对象的管理的。当类的是前两个字母都是大写时,直接以这个类名作为存储的bean对象的身份标识,否则将类的第一个字符转换为小写作为存储的bean对象的标识!下面我们来验证一下:
3. 读取Bean对象
从ioc容器中读取Bean对象又称为对象装配,有时候也叫做对象注入。总共有以下三种注入方式,均是通过@Autowired或者@Resource注解来实现的:
- 属性注入——@Autowired/@Resource
- 构造方法注入——@Autowired/@Resource
- Setter注入——@Autowired
其中,@Autowired注解可以用于标注 属性注入、Setter注入以及构造方法注入;而@Resource只能用于标注 属性注入和Setter注入,布恩那个用于标注构造方法注入!
下面我们通过将IOC容器中的服务层的UserService对象注入到IOC容器中的控制层的UserController对象中,并且在UserController对象中调用服务层的方法,来学习这三种注入读取Bean对象的方式——操作【1】。
3.1 属性注入
实现:在类的成员属性上加上@Autuwired注解,表明该属性要被Spring注入。
我们来学习通过属性注入的方式实现上述操作【1】
3.2 setter注入
实现:在成员属性中定义注入对象引用,并为其添加setter方法,在setter方法上加上@Autowired注解表明要进行Setter注入操作。
我们来学习通过Setter注入的方式实现上述操作【1】
3.3 构造方法注入
实现:在当前类的构造方法上加上@Autowired注解,在形参上指定Spring要注入的对象及其类型,将该对象赋值给成员属性上的引用变量,完成构造方法注入。(当当前类中的构造方法只有一个时,可以省略构造方法上@Autowired注解的标注)。
我们来学习通过构造方法注入的方式实现上述操作【1】
使用构造方法注入的注意事项:
- 用于实现构造方法注入的构造方法中的形参的参数只能注入对象一个!
- 当前注入类中有多个构造方法时,就不能省略@Autowired注解!
3.4 注入异常问题
使用上述的注入方式可能存在下边的这种问题:
当我们的ioc容器中存在了多个相同类型bean对象,再通过上方的注入方式来获取的话,程序就会报异常!我们来模拟一下这种情况以及记录这种情况的解决办法。
那么,应该如何解决上述的问题呢?
这个时候就需要我们的@Resource或者@Qualifier注解上场了!上述问题共分为以下两种情况来解决:
3.5 注入方式优缺点
Spring的依赖注入/对象装配有哪几种方式?它们之间有什么区别?
Spring共有三种依赖注入方式,分别是属性注入,Setter注入以及构造方法注入。它们之间的区别如下:
- 属性注入
优点:书写简洁,使用方便。
缺点:无法注入一个不可变对象(被final修饰的引用所引用的对象);只适用于IOC容器;并且比较容易违背单一设计原则。- Setter注入
优点:更加符合单一设计原则。
缺点:依然不可注入不可变对象;由于Setter方法时public的,所以注入的对象可以被随时修改。- 构造方法注入
优点:可以注入不可变对象;并且只会在类加载时执行一次;注入对象会被完全初始化;当当前类中只有一个构造方法时 ,可以省略注解标注,通用性较好。
3.6 @Autowired和@Resource的区别
- 出身不同:@Autowired来自Spring,@Resource来自于JDK
- 使用时参数设置不同:@Resouce相对于@Autowired来说支持更多的参数配置。
最常见的例如@Resource可以配置name属性来从ioc容器中获取Spring管理的对象,@Autowired则不能配置name属性。- @Autowired可以用于三种注入方式属性注入、Setter注入以及构造方法注入中的任何一种,而@Resource只能用于属性注入和Setter注入标注。