文章目录
01 Spring全家桶
- Spring Framework
(Spring框架 基石 核心) - Spring Boot
(构建项目 更容易) - Spring Cloud
(微服务 很大的项目维护困难 可拆分成若干个子项目 把它们集成在一起 每个子项目规模比较小 便于维护) - Spring Cloud Data Flow
(数据集成 很多客户端 数据形态各异 集成一起)
02 spring核心模块
- Spring Core
IOC(重要)、AOP - Spring Data Access
Transactions、Spring Mybatis - Web Servlet
Spring MVC - Integration
Email、Scheduling、AMQP、Security
03 Spring IOC
- Inversion of Control
控制反转,是一种面向对象编程的设计思想(减少beans的耦合度)。 - Dependency Injection
依赖注入,是IOC思想的实现方式。 - IOC Container容器
IOC容器,是实现依赖注入的关键,本质上是一个工厂。
提供两份数据:
1.管理哪些beans(beans的类型)
2.配置文件(描述类与类之间的关系,自动实例化beans)
bean与bean之间不会产生直接关联,类与类之间的耦合是通过配置文件体现的。
配置类SpringApplication
启动类中SpringApplication.run(CommunityApplication.class,args)底层启动了tomocat,并且在Web项目中自动创建了spring容器,然后自动扫描某些包下的bean,将这些bean装配到容器中。
@SpringBootApplication注解
通过代码演示IOC使用方式
(测试类中演示)
1.添加注解@ContextConfiguration
正式运行程序是运行CommunityApplication这个类(配置类,一运行以它为配置类来执行程序),如果希望测试代码中也用这个配置类,也希望和正式环境用配置类相同,启用这个类作为配置类,只需要加上注解
@ContextConfiguration(classes = CommunityApplication.class)。
2.得到spring容器
Q:IOC核心是Spring容器,而容器又是被自动创建的,怎么得到这个容器呢?
哪个类想得到这个容器,只需要:
- 实现接口:ApplicationContextAware
- 实现方法:setApplicationContext
如果一个类实现了ApplicationContextAware接口的setApplicationContext方法,那么Spring容器会检测到,Spring容器再扫描组件时会检测到这样的bean,然后调用setApplicationContext把自身applicationContext(容器)传进来。(暂存applicationContext后面则可使用。)
applicationContext这个参数就是Spring容器,它是一个接口。
ApplicationContext —> 继承自 —> HierarchicalBeanFactory --> 继承自 --> BeanFactory
BeanFactory就是bean工厂,它其实就是Spring容器的顶层接口。ApplicationContext是它的子接口BeanFactory,比父接口扩展出了更多方法,功能更强所以我们通常会用子接口ApplicationContext。
Spring的本质是一个bean工厂(beanFactory)或者说bean容器,它按照我们的要求,生产我们需要的各种各样的bean,提供给我们使用。只是在生产bean的过程中,需要解决bean之间的依赖问题,才引入了依赖注入(DI)这种技术。也就是说依赖注入是beanFactory生产bean时为了解决bean之间的依赖的一种技术而已。
Q:那么我们为什么需要Spring框架来给我们提供这个beanFactory的功能呢?
1.可以将原来硬编码的依赖,通过Spring这个beanFactory这个工厂来注入依赖,也就是说原来只有依赖方和被依赖方,现在我们引入了第三方——spring这个beanFactory,由它来解决bean之间的依赖问题,达到了松耦合的效果;
2.在没有spring这个beanFactory之前,我们都是直接通过new来实例化各种对象,现在各种对象bean的生产都是通过beanFactory来实例化的,这样的话,spring这个beanFactory就可以在实例化bean的过程中,做一些小动作——在实例化bean的各个阶段进行一些额外的处理,也就是说beanFactory会在bean的生命周期的各个阶段中对bean进行各种管理,并且spring将这些阶段通过各种接口暴露给我们,让我们可以对bean进行各种处理,我们只要让bean实现对应的接口,那么spring就会在bean的生命周期调用我们实现的接口来处理该bean。
3.记录Spring容器
加入成员变量applicationContext,记录Spring容器applicationContext。
4.测试方法中使用容器
假设用Hibernate来实现的。
得到查询结果,没有问题。
但是这样很麻烦,为什么不自己实例化,有什么好处?
比如说项目发展到一定阶段,有一个新的技术Mybatis诞生了,比Hibernate更有优势,在项目中想把Hibernate替换成Mybatis,我们可以新建一个Dao的实现类而不用删掉原先的。
此时会产生歧义,报错
解决办法:在希望的bean上再加一个注解@Primary,此时被调用时这个bean拥有更高的优先级,会被优先装配
成功运行
这就是它的优势,我的程序当中,原先所有dao的实现类都使用Hibernate实现,调用这个bean的地方会很多的,有一天我们要替换掉这个bean时,只需要再加一个bean,多加一个@primary注解就行,我们为你调用的地方完全不用变,因为我们调用的地方,依赖的不是bean本身,依赖的是接口(面向接口编程的思想:依赖的是接口,实现类变了,接口不用动),降低了bean之间的耦合度,调用方和实现类不会发生任何的直接关系。
当然也会产生新问题: 比如程序的某一块还想用Hibernate,不想用MyBatis,但上述方法获取的永远是Mybatis的实现,那怎么得到Hibernate实现的bean呢?
每个bean都拥有名字,每个bean默认的名字是类名首字母小写,也可以自定义。
5.容器管理bean初始化和销毁的方法
查看日志
程序启动时bean被实例化,程序停止时bean被销毁,说明bean只被实例化一次,只被销毁一次,它在容器中只有一个实例,单例的。
测试是否单例:
确实是单例的,如果不希望是单例的,可加注解:@Scope(“prototype”)
spring容器管理bean的作用于范围
@Scope("prototype")//多实例,IOC容器启动创建的时候,并不会创建对象放在容器在容器当中,当你需要的时候,需要从容器当中取该对象的时候,就会创建。
@Scope("singleton")//单实例 IOC容器启动的时候就会调用方法创建对象,以后每次获取都是从容器当中拿同一个对象(map当中)。
@Scope("request")//同一个请求创建一个实例
@Scope("session")//同一个session创建一个实例
6.Spring容器管理第三方bean
(以SimpleDateFormat为例)