Spring核心概念
一,Spring介绍
Spring家族主要框架:
上述三套构成了当先互联网java后端开发的百分之九十的技术框架。
-
Spring Cloud:这是一个微服务框架,旨在简化分布式系统的开发。它提供了一系列工具,用于处理诸如服务发现、配置管理、负载均衡、断路器、路由、微代理、事件驱动数据以及分布式消息传递等问题。Spring Cloud构建在Spring Boot之上,利用Spring Boot的简化配置能力,使得开发和部署微服务变得更加容易。
-
Spring Framework:这是一个功能强大的全方位Java应用程序开发框架。Spring Framework不仅限于单体应用,它也可以用于构建微服务和企业级应用。它提供了全面的基础设施支持,包括依赖注入(DI)、面向方面编程(AOP)、数据访问、事务管理、Web应用程序开发等。
-
Spring Boot:这是一个基于Spring Framework的项目,旨在简化Spring应用的创建和配置。Spring Boot通过自动配置和“开箱即用”的默认值,减少了开发人员配置应用的繁琐过程。它适用于构建独立、生产级的Spring应用,无需复杂的XML配置。
Spring的发展史:
二,Spring系统架构图
三,IoC与DI概念
在我们没使用Spring框架之前,我们调用其他类里面的方法都是通过new对象来创建的,但是这样会让代码之间的耦合度变高,当我们new的对象的那个类需要进行切换时,成本较高,需要重新编译,故通过IOC的方式来实现类之间的解耦。
-
IoC(Inversion of Control)控制反转:
- 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转
-
Spring技术对Ioc思想进行了实现:
- Spring提供了一个容器,叫IoC容器,用来充当Ioc思想中的“外部”
- IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
-
DI(Dependency Injection)依赖注入:
- 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
内聚:软件中各个功能模块内部的功能联系。
耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
软件设计原则:高内聚低耦合使用IoC和DI的目标:充分解耦
-
使用IoC容器管理bean(IoC)
-
在IoC容器内将有依赖关系的bean进行关系绑定(DI)
最终效果:使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
四,IoC与DI(XML版)
4.1 Ioc
注:xml版是Ioc和DI的早期使用方式,实际开发中我们是通过注解版来实现Ioc和DI开发的
-
导入Spring坐标
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency>
-
-
注意:
- bean的id不能重复
- bean标签表示配置bean
- id属性标示给bean起名字
- class属性表示给bean定义类型(就是这个bean的位置)
-
4.2 DI
-
-
还需要提供无参构造函数
-
注:
- property标签表示配置当前bean的属性
- name属性表示配置哪一个具体的属性
- ref属性表示参照哪一个bean
五,Bean配置
5.1 Bean基础配置
5.2 Bean别名配置
在xml配置文件中,我们可给Bean起别名如下所示:
<!--通过name属性来起别名,并且可以同时起多个别名,多个别命用逗号分隔-->
<bean id="iocService" name="service,service2,service3" class="IocDemo.service.impl.iocServiceImpl">
<property name="mapper" ref="mapper"/>
</bean>
<!--这个别名针对ref属性也是可使用的-->
<bean id="iocMapper" name="mapper" class="IocDemo.dao.impl.iocMapperImpl"/>
5.3 Bean作用范围配置
为什么Bean默认是单例的:
- 资源节约:单例模式确保每个bean在整个应用程序中只有一个实例,这样可以节省内存和CPU资源。对于一些重型对象,频繁创建和销毁会消耗大量资源,使用单例可以显著提高性能。
- 管理方便:单例bean由Spring容器管理,整个应用程序在启动时创建并初始化它们,然后在整个应用程序生命周期内重用这些实例。这样可以减少复杂性,简化bean的管理和使用。
- 线程安全:单例bean通常在初始化时就已经准备好可以使用,而不是在每次请求时创建新实例。因此,如果单例bean是线程安全的,它们可以安全地被多个线程共享,而不需要额外的同步开销。
- 一致性:用单例bean可以确保同一类型的bean在整个应用程序中具有一致的状态。这对于某些全局配置或共享资源来说特别重要,例如数据库连接池、缓存管理器等。
适合交给容器进行管理的bean
-
表现层对象controller
-
业务层对象service
-
数据层对象dao
-
工具对象utils
不适合交给容器进行管理的bean
- 封装实体的域对象
六,Bean的初始化
6.1 构造方法初始化Bean
bean本质上就是对象,创建bean使用构造方法完成。
- Spring底层是通过反射,调用无参构造来实现实例化bean的
6.2 静态工厂初始化Bean
这种方式一般是为了兼容早期的遗留系统来使用的,了解即可。之所以必须用静态工厂是因为静态工厂里面包含了一些实例化类必须的操作。
6.3 实例工厂初始化Bean
6.4 实现FactoryBean初始化Bean
在很多的Spring集成框架里面都是使用这种方式的。
-
工厂类:
public class UserDaoFactory implements FactoryBean<IUseDao> { @Override public IUseDao getObject() throws Exception { //这个方法用来创建bena对象 return new UserDaoImpl(); } @Override public Class<?> getObjectType() { //这个方法用来返回bean对象的字节码对象 return IUseDao.class; } @Override public boolean isSingleton() { //这个用来决定创建的bean对象是单例的还是非单例的 //true是单例 //false是非单例 return false; } }
-
xml配置
<bean id="UserDaoFactory" class="IocDemo.factory.UserDaoFactory" /> <!--直接将工厂给配置成bean即可-->
七,Bean的生命周期
生命周期:从创建到消亡的完整过程
- bean生命周期:bean从创建到销毁的整体过程
- bean生命周期控制:在bean创建后到销毁前做一些事情
Bean的生命周期:
-
初始化容器:
-
创建对象(内存分配 )
-
执行构造方法
-
执行属性注入(set操作)
-
执行bean初始化方法
-
使用bean
-
-
执行业务操作
- 关闭/销毁容器
- 执行bean销毁方法
7.1 生命周期控制
使用xml方式配置生命周期控制
使用接口实现生命周期的控制:
7.2 Bean的销毁
八,依赖注入
8.1 Setter注入
8.1.1 注入简单类型
8.1.2 注入引用类型
8.2 构造器注入
8.2.1 注入简单类型
使用构造器注入中的name指的是形参名
8.2.2 注入引用类型
8.2.3 参数适配
由于使用构造器注入使用的是形参名匹配,导致耦合度过高,故有如下方式进行解耦合
8.3 依赖注入选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
8.4 自动装配
IoC容器根据bean所依赖的资源在容器中自动査找并注入到bean中的过程称为自动装配
自动装配方式:
- 按类型(常用)
- 按名称
- 按构造方法
- 不启用自动装配
byType
-
那么在bean容器中这个类型的bean只能有一个要不然会报错,因为Spring不知道选择哪一个bean注入
-
按类型,那个注入的bean不需要写id
byName:
- 他是通过setXXX来识别的,加上我选择是setA,并且存在A这个Bean就会注入A,如果Bean的id叫A但set方法是setB会出现识别失败的情况
按构造方法自动注入是不推荐使用的,因为是强依赖注入,故不采用
- 自动装配用于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
- 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
- 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
8.5 集合注入
如果集合的泛型是引用数据类型的,那么用ref来代替value即可
-
<ref bean="beanId"/>
九,加载properties文件
十,容器
10.1 容器初始化
10.2 获取bean
10.3 容器层次结构图
10.4 BeanFactory初始化(了解)
ApplicationContext也可以延迟加载
-
<bean id="userDao" class="IocDemo.dao.impl.UserDaoImpl" lazy-init="true"/>