🙉专栏推荐:Java入门知识🙉
🐹今日诗词:春有百花秋有月,夏有凉风冬有雪🐹
⛳️点赞 ☀️收藏⭐️关注💬卑微小博主🙏
⛳️点赞 ☀️收藏⭐️关注💬卑微小博主🙏
目录
Spring
容器
介绍Spring IoC, 首先要了解容器的概念
容器: 可以容纳对象, 例如链表, 队列, 堆, map....
Spring也是一个容器, 它容纳的是一个Bean对象
Java SE的Bean对象指的是实体类
Spring的Bean对象指的是Spring管理的对象, 例如这个
Spring IoC
IoC(Inversion of Controller): 控制反转
前面通过@RestController和@Controller注解, 把类交给Spring去管理, 这个思想就是IoC思想
控制反转: 指的是控制权反转
比如汽车驾驶: 以前是驾驶员开车, 现在可以交给自动化驾驶系统, 这也属于控制反转
我们接下以 制造一个汽车 为例子 来对比传统方式和IoC方式
传统程序和IoC程序
传统方式
要想汽车跑,需要先造一个汽车
造汽车,需要先造车身
造车身,需要先造底盘
造底盘,需要先造轮胎
确定轮胎尺寸并制造
于是汽车就可以运行了
传统方式问题
可维护性太差,当最底层代码改动之后, 整个调⽤链上的所有代码都需要修改, 牵一发而动全身
比如客户想要不同的轮胎大小, 我们按需求设计轮胎大小, 在轮胎类构造方法里传入size,
会报错, 整个调⽤链上的所有代码都需要修改
IoC方式
IoC写法需要对代码进行修改, 需要对象时,传一个对象, 这个对象可以从Spring中拿
因为我们把对象交给Spring去管理, 如果我们需要, Spring就会帮我们创建
优点
代码耦合性低, 增加需求对其他类和方法影响很小
如何把对象放到Spring中
@Component注解: 把对象放到Spring中
@Component注解是加在类上的
如何从Spring中取出对象
@Autowired注解: 从Spring中取出对象, 注入到对象的使用方(这个过程叫依赖注入, 又称Di)
@Autowired注解是加在对象上的
Spring存储对象
通过Spring容器存储对象, 一般通过注解从容器获取对象, 注解类型有两种:
类注解: @Controller, @Service, @Repository, @Componment, @Configuration(五大注解)
方法注解: @Bean(唯一)
IoC注解的应用
@Controller注解
前面我们也了解过, @Controller注解有很多功能,
在Spring知识里, 被@Controller注解标记的类, 在Spring容器启动时, 会创建实例并作为bean对象存储到容器中
@Controller其他作用:
- 请求映射: 能够将Http的 URL 请求映射到相应的方法上
- 视图解析:通常会返回一个视图
- 标识控制器:用于标识一个类为Spring MVC的控制器, 表示这个类是处理用户请求的组件
@Controller的使用
我们不手动创建对象, 借助@Controller注解和Spring容器来调用对象的方法, 例如
@Service的使用
使用方式和@Controller注解一样, 加在类上的
@Service
注解用于标记业务逻辑层访问对象@Service注解标记的类, 在Spring容器启动时, 会创建实例并作为bean对象存储到容器中
从容器获取对象的常用方式
我们一般通过ApplicationContext接口的方法从容器获取对象
ApplicationContext接口的getBean方法有很多种重载方式
我们介绍一下常见的三种
根据类型从容器获取对象
方法: getBean(Class<T> requiredType)
括号里填: 要获取对象的类型
这串代码要获取对象的类型是UserService
根据名称从容器获取对象
方法: getBean(String name)
name: 是容器创建对象的名称
那么我怎么知道容器创建对象叫啥名呢?
Spring容器对象命名规范
五大注解命名规则: 一般情况采用小驼峰的形式
即首字母小写, 后续单词的首字母大写, 没有空格或下划线
例如: UserController -------> userController
特殊情况, 如果类名第一个字母和第二个字母都是大写, 则容器对象名保持不变
例如UController ------> UController
方法注解: @Bean注解命名规范
如果是@Bean注解: 容器对象名称是方法名
根据类型和名称从容器获取对象
方法: getBean(String name, Class<T> requiredType)
双重保险: 根据类型和名称从容器中获取对象
Spring创建对象是单例模式, 我们每次从容器获取一个Bean时,都会返回同一个实例
所以三次获取输出都是同一个实例
@Repository
@Repository
用于标识数据访问对象(DAO)@Repository注解标记的类, 在Spring容器启动时, 会创建实例并作为bean对象存储到容器中
@Component
@Component
是一个通用的标记注解,适用于任何需要被Spring管理的类
@Configuration
用于定义应用的Bean配置
@Configuration注解标记的类, 在Spring容器启动时, 会创建实例并作为bean对象存储到容器中
五大注解的关系
@Bean注解(方法注解)
作用: Spring会将 被@Bean注解标记的方法 的返回值作为示例放在容器中
@Bean注解要搭配类注解使用, 没有类哪来的方法
前面的五大注解是单例模式实现的, 每次请求都只返回一个实例
如果想要返回多个对象需要用到@Bean注解
注解重命名
如果不想用Spring提供的容器名称, 我们也是可以自己命名的
五大注解重命名: 直接在注解后面加括号重命名即可
例如@Reposiotry("name")
在Spring容器的名称: 和Spring默认的规则无关, 你起啥名, 在容器里面还是啥名
方法注解重命名@Bean
分两种情况, 一种和五大注解命名方法一样另一种: 同一个Bean对象定义多个名称, 重命名多个名称采用数数组的形式
@Bean( {"name1", "name2"} )
两个名字, 都指向同一个对象
Spring扫描路径
前面我们学了Spring会扫描加注解的类并执行, 并不是所有加注解的类都会被扫描到
必须是和启动类所在路径相同的路径或其子路径, 并且加了注解才会扫描
毕竟子目录不能扫描父目录
我们把启动类挪到Repository包下
指定扫描路径
@ComponentScan(文件路径)
依赖注入
依赖注入分三种: 属性注入, Setter方法注入, 构造方法注入
依赖注入和五大注解一样, 也是将类对象交给Spring容器去管理
疑问: 五大注解不是已经交给容器进行管理了吗, 为什么还要依赖注入?
答: 他们之间是相辅相成的, 有了五大注解并不代表就不要依赖注入了,
就像有女朋友, 不一定代表就不能找小三了(请勿代入)
有时候即使一个类被五大注解标注, 但是类中还是有可能会用到其他类里的字段, 我们使用其他类的字段或方法时仍然需要手动new
而依赖注入是将对象的依赖关系管理交给Spring容器来完成,而不是由类本身来创建和管理这些依赖.
属性注入
语法: 在需要注入的属性前面加上@Autowired注解
Spring就会帮我们把创建好的对象赋值给声明的属性了
首先要声明可能要用到的类, 只是声明, 并不是创建对象, 赋值对象的过程交给Spring容器
属性是
Setter方法注入
语法: 在Setter方法前面加上@Autowired注解, Spring就会帮我们注入了
构造方法注入
语法: 在有参构造方法前面加上@Autowired注解即可
三种注入方式的差异性(重点)
@Autowired注解存在的问题
问题: 当存在多个相同类型的Bean注入时,会导致Spring无法确定要注入哪一个Bean.
@Primary注解
作用: @Primary
注解用于标记优先注入的Bean,当有多个相同类型的Bean时,Spring会优先选择标有@Primary注解的Bean对象
@Qualifier注解
作用: 如果Spring有多个相同类型的Bean, 可以使用@Qualifier注解指定具体要注入的Bean
这种注入方法使用的更多, 因此@Qualifier注解可读性更高, 是加在要注入对象前面的, 而@Primary注解是
加在创建对象的时候
@Resource注解
@Resource注解是JDK包里的, 也可以用于依赖注入
作用:
Resource
用于自动注入Bean,根据名称或类型进行注入, 一般多用于根据名称注入
此外还有一种方式不同@Primary和@Qualifier和@Resource注解实现注入的方式
方法: 让创建的对象名和容器中的Bean名相同
四种注入方式选择哪种比较好
通常情况下,我们认为:
@Autowired适用于一个类只有一个对象,如果有多个对象
一般会使用@Resource来完成注入
@Autowired注入过程
美图分享