Ioc基本概念
全称: Inversion of Control (IOC) 名为:控制反转 轻量级容器
控制权转移,将我们创建的对象的方式反转了,以前的对象的创建时由开发人员自己维护,包括依赖对象也是自己注入,使用了spring之后,对象的创建以及依赖关系可以由spring完成创建以及注入,反转控制就是反转了对象的创建方式,从我们自己创建反转给了程序创建(Ioc Service Provider)
别名 :DI 依赖注入 Dependency Injection 可以看作IOC注入的一种方式。
底层原理: XML 解析 工厂模式 反射
Ioc注入方式
构造方法注入
通过其构造方法中声明依赖对象的参数列表,通过Ioc检查注入对象的构造方法,取得依赖对象列表,从而注入对象。
setter方法注入
与构造方法相似,一个类中通常都有getXXX和setXXX方法访问类属性。Ioc通过调用setter方法取得依赖对象并设置到注入对象中。
接口注入
接口注入相对复杂,通过接口注入依赖对象,则注入对象必须实现某接口,该接口必须提供一个可以注入依赖对象的方法。该方法的参数就是所依赖对象的类型。
三种注入方式的比较:
1、接口注入基本不使用。由于可能需要实现不必要的接口,带有侵入性。
2、构造方法注入,对象构造完成后,立即进入准备状态,马上使用。缺点:对于参数过多的构造方法,参数列表较长,使用和维和麻烦,不可设置默认值,不可被继承,对参数数量的变动维护不变。
3、setter方法注入。方法名自定义,可以被继承,允许有默认值。
Ioc优势
降低组件之间的耦合度,实现软件各层之间的解耦.
Ioc Service Provider
职责:业务对象的构建管理和业务对象间的依赖绑定。
Ioc Service Provider管理对象方式
1、直接编码方式
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ek6rTRnO-1646801947200)(C:\Users\崔常菲\AppData\Roaming\Typora\typora-user-images\image-20210903213606107.png)]](https://img-blog.csdnimg.cn/dbba5daa51544d9ba3f7fcc13f1f68b6.png
通过为响应类指定对应的具体实例,告知Ioc容器,当需要对象实例时,将容器中的实例返回给我们。
2、配置文件方式
Spring采用XML文件管理和保存依赖注入关系。
3、元数据方式
以注解的方式,可以在类中那个使用元数据信息来标注各个对象之间的依赖关系。
Ioc容器之Beanfactory
两种容器类型:
1、Beanfactory :基础类型Ioc容器,对资源有限,并且要求不严格的场景,选用该容器 Interface
(1) spring的原始接口,针对原始接口的实现类功能较为单一
(2)BeanFactory接口实现类的容器,特点是每次在获得对象时才会创建对象
2、ApplicationContext 继承于Beanfactory,在Beanfactory的基础上构建,高级容器实现,支持所有Beanfactory。较Beanfactory 需要更多资源,启动时完成所有初始化,启动时间较Beanfactory长。
(1)每次容器启动时就会创建容器中配置的所有对象
(2)提供了更多功能
(3)从类路径下加载配置文件: ClassPathXmlApplicationContext
从硬盘的绝对路径下加载配置文件:FileSystemXmlApplication
关系:
Beanfactory接口中getBean方法 获取对象的方法,containBean查询某个对象是否存在容器中的方法。
getBean(String name,Class requiredType)
containBean(String name)
Beanfactory的对象注册于依赖绑定方式
1、直接编码方式
DefaultListableBeanFactory是BeanFactory一个通用实现类,DefaultListableBeanFactory间接实现Beanfactory接口。
2、外部配置文件方式
配置流程:
根据不同的文件格式给出相应的BeanDefinitionReader实现类,由BeanDefinitionReader的相应实现类负责将将相应的配置文件内容读取并映射到BeanDefinition,然后将映射的BeanDefinition注册一个BeanDefinitionRegistry,之后BeanDefinitionRegistry完成Bean的注册和加载。
Ioc容器支持properties和XML两种文件格式
①properties 配置 是按照Spring自己文件配置规则进行加载,可以自定义.
PropertiesBeanDefinitionReader类实现Properties格式配置文件加载
②XML配置
XMLBeanDefinitionReader类负责读取并解析XML文件配置
③注解方式 需要在XML文档内配置 classpath-class
<context:component-scan base-package = ‘’ classpath-class’’/>
@Autowired 告诉Spring容器注入对象
@component 对相关类进行标记
Beanfactory的XML
1 、beans 和bean
所有的均在之下
默认设置: lazy-init :延迟初始化 true false 默认no
autowire 绑定方式 byType byName no 默认no
dependency-check 依赖检查none objects simple all 默认none
init-method 初始化方法 在 和设置
destory-method 销毁方法 在 和设置
配置文件描述信息,非必须
从A.XML引入B.XML是使用 形式 多个XML文件时,可以使用
对bean取别名
属性:
①id属性 与name属性一模一样,名称不可重复,不能使用特殊字符
②name属性 给被管理的对象起个名字,获得对象时getBean(“name值”),可以使用特殊字符 可以用alias取别名
③class 属性 被管理对象的完整类名(类路径)
2 、构造方法注入
① <name = “构造函数参数名”> 输入构造函数参数名
②<index = “构造函数参数下标(从0开始)”> 功能于name相似 可替换name
③<value = “参数值”>
④<type = “参数类型”>构造函数的参数类型
或者
⑤<ref = "依赖对象名称">
3、setter方法注入
① <name = “构造函数参数名”> 输入构造函数参数名
②<value = “参数值”>
③<index = “构造函数参数下标(从0开始)”> 功能于name相似 可替换name
或者
④<ref = “依赖对象名称”> 内嵌其他元素来指定具体的依赖对象引用
4、properties和constructor-arg可用的配置项
(1) 值 最底层元素 不可嵌套任何元素
(2) 用于引用容器中的其他对象,其包含 local parent 和 bean属性来表名引用对象的beanName是什么
①local 指定当前配置对象在同一配置文件的对象定义的名称
②parent 指定位于当前容器的父容器中定义的对象的引用(Beanfactory可以分层次,通过实现HierarchicalBeanFactory接口,实现容器A,引用容器B)
③bean 以上均可,一般用bean
(3) 为当前依赖对象注入所依赖对象 不常用
作用同于:
(4) 内部 bean内部嵌套
(5)
… …
(6)
… …
(7)
… …
(8)
(9)
当对象为String类型时, 不等价于""
==
5、显式依赖
若一个类需要初始化代码
<depends-on =“依赖对象”> 显示指定bean之间的关系
6、autowire
<autowire = “”>
Spring提供了五种自动绑定关系: no byType byName constructor autodetect 默认no
no 不采用任何自动绑定
byType 按实例变量类型自动绑定
byName 按实例变量名称自动绑定 与beanName的值进行匹配
constructor 按构造方法参数类型进行自动绑定
autodetect byTyoe和constructor,若默认无参数的构造方法,容器会优先考虑byType的自动绑定模式,否则使用constructor模式绑定
7、dependency-check
<denpendecy-check = “”>
每个bean都有一个dependency-check属性,其所有来的对象进行最终检查
none 默认值,不进行检查
simple 顾名思义简单检查,只对相关collection进行检查,对象引用类型的依赖除外.
object 只对对象引用类型依赖进行检查
all = simple + object
该一般属性不使用
8、lazy-init 延迟初始化
<lazy-init = “ture or false”>
延迟某些bean或者某个beanApplicationContext默认初始化时机.
为保证该bean定义的其他bean定义也同样设置为延迟初始化
一般在中统一设置
9、bean中的继承
<parent = “父类名称”>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KkQ3Xi52-1646801947204)(C:\Users\崔常菲\AppData\Roaming\Typora\typora-user-images\image-20210904154857846.png)]
10、bean中的scope
<scope="">
singleton Spring在Ioc中只会存在一个实例,该属性下,通过getBean得到的对象,指向同一个对象
prototype 每次请求都会返回一个新的实例
request 针对Web 每次HTTP请求都会建立一个全新的对象,为prototype特例
session 对每个session都会常见新的UserPreferences对象实例
工厂方法和工厂bean
1、静态工厂方法
获得实例的方法为静态方法
<factory-method = “静态工厂方法”>
2、非静态方法
获得实例的方法为非静态方法
<factory-method = “静态工厂方法”>
3、FactoryBean
通过工厂Beanfactory,配置文件定义的Bean类型可以和返回类型不一样
FactoryBean创建步骤:
①创建类,作为工厂Bean.实现FactoryBean
②重写接口方法,在getObject方法中返回需要的Bean类型
FactoryBean为Bean提供的一个实例化接口,其定义了三个方法
getObject()方法会返回该FactoryBean“生产”的对象实例,我们需要实现该方法以给出自己 的对象实例化逻辑;
getObjectType()方法仅返回getObject()方法所返回的对象的类型,如果预先 无法确定,则返回null;
isSingleton()方法返回结果用于表明,工厂方法(getObject())所“生 产”的对象是否要以singleton形式存在于容器中。如果以singleton形式存在,则返回true,否则返回false;
scope陷阱
当bean中的scope属性定义为prototype后,每次实例化返回一个全新的该对象实例,
存在下面特例:
通过getBean获得实例,每次调用persistNews方法时,都会调用,getNewsBean方法,该方法多次调用的方法,都是指向同一个引用对象,所以要解决getBean调用单一实例.
1、注入方法
通过的name属性指定需要注入的方法名,bean属性指定需要注入的对象,当 getNewsBean方法被调用的时候,容器可以每次返回一个新的FXNewsBean类型的实例。
2、使用BeanFactoryAware接口
实现该接口里面的setBeanFactory方法
3、方法替换
不建议这么做
容器背后的秘密
Ioc容器分为容器启动阶段和Bean实例化阶段
1、容器启动阶段
容器通过某些工具类将XML文档解析并编为相应的BeanDefinition,保存Bean必要的信息BeanDefinition,注册BeanDefinitionRegistery.
映射流程:
BeanFactoryPostProcessor容器扩展机制,对注册到BeanDefinition的信息做出相应的修改.
①PropertyPlaceholderConfigurer
该类允许在XML配置文档中使用占位符(PlaceHolder) 例如连接数据库的4条基本信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--直接配置连接池-->
<!--<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>-->
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
</beans>
PropertyPlaceholderConfigurer不单会从其配置的properties文件中加载配置项,同时还会检 查Java的System类中的Properties,可以通过setSystemPropertiesMode()或者setSystemPropertiesModeName()来控制是否加载或者覆盖System相应Properties的行为。
②PropertyOverrideConfigurer
可以通过PropertyOverrideConfigurer对容器中配置的任何你想处理的bean定义的property信息进行覆盖替换。
③ CustomEditorConfigurer
2、实例化过程
当getBean方法请求某个对象时,会根据注册的BeanDefinition所提供的信息实例化被请求对象.
Bean的生命周期
简化过程:
①通过构造器创建Bean实例(无参数构造)
②为bean的属性设置值和对其他bean引用(调用set方法)
③把bean实例传递给bean后置处理方法postProcessBeforeInitialization
④调用bean初始化方法(需要配置init-method)
⑤把bean实例传递给bean后置处理方法postProcessAfterInitialization
⑥使用bean
⑦容器关闭.调用bean销毁方法(需要配置destory-method)
其中③和⑤需要创建类,实现BeanPostProcessor,重写postProcessBeforeInitialization和postProcessAfterInitialization方法,在XML文档内需要配置后置处理器
各种Aware接口
BeanNameAware 该对象实例的bean定义对应的beanName设置到当前对象实例
BeanClassLoaderAware 容器检测到当前对 象实例实现了该接口,会将对应加载当前bean的Classloader注入当前对象实例。
BeanFactoryAware 将自身设置到当前对象实例
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware
Ioc容器ApplicationContext
Spring为基本的BeanFactory类型容器提供了XmlBeanFactory实现。
ApplicationContext提供了如下实现:
FileSystemXmlApplicationContext 从文件系统加载bean定义以及相关资源的ApplicationContext实现
ClassPathXmlApplicationContext 从Classpath加载bean定义以及相关资源的ApplicationContext实现
Spring资源加载策略
Resource接口作为所有资源的抽象和访问接口
提供如下类以供实现:
①ByteArrayResource 将字节(byte)数组提供的数据作为一种资源进行封装,如果通过 InputStream形式访问该类型的资源,该实现会根据字节数组的数据,构造相应的ByteArrayInputStream并返回。
②ClassPathResource 该实现从Java应用程序的ClassPath中加载具体资源并进行封装,可以使 用指定的类加载器(ClassLoader)或者给定的类进行资源加载。
③FileSystemResource 我们可以以文件或者URL的形 式对该类型资源进行访问,只要能跟File打的交道,基本上跟FileSystemResource也可以。
④UrlResource 通过java.net.URL进行的具体资源查找定位的实现类,内部委派URL进行具 体的资源操作。
⑤InputStreamResource 将给定的InputStream视为一种资源的Resource实现类,较为少用。 可能的情况下,以ByteArrayResource以及其他形式资源实现代之。
ResourceLoader 接口
用于定位和查找资源
提供如下类:
①DefaultResourceLoader
②FileSystemResourceLoader
③ ResourcePatternResolver ——批量查找的ResourceLoade
ApplicationContext与Resource
通过ApplicationContext来加载任何Spring支持的Resource类型,ApplicationContext容器本身就是一个ResourceLoader
国际化信息支持
1、Locale类
提供了三个构造方法
Locale china = new Locale(“zh”,“CN”);
相当于 Locale.CHINA
Locale.CHINA代表中国,表示zh_CN
Locale.US代表美国地区,代码表示为en_US
2、ResourceBundle类
用来保存特定于某个Locale的信息(可以是String类型信息,也可以是任何类型的对象)
3、MessageSource 接口
该接口定义了三种方法,实现该接口需要重写下列方法
他有以下实现类:
基于注解方式的Ioc操作Bean管理
格式: @注解名称(属性名称=属性值,属性名称=属性值)
Spring 针对 Bean 管理中创建对象提供注解
(1)@Component (2)@Service (3)@Controller (4)@Repository
- 上面四个注解功能是一样的,都可以用来创建 bean 实例,一般在不同地方规定使用某一个关键字。提高可读性
基于注解方式实现对象创建步骤
①引入spring-aop-release依赖
②在XML文件中开启扫描
<context:component-scan base-package=“目录名”></context:component-scan>>
③ 创建类 ,在类上添加创建对象注解
@Component(value = “对象名”) //不写value 默认对象名为类名开头字母为小写
class 类名{
}
等价于
④扫描细节配置 可以设置哪些不扫描、哪些扫描
<use-default-filters = “false ot true”> 是否是哟默认的filters ,若为false,自己设置扫描内容。
<use-default-filters = “false” type = “Component or Service …”>对某一注解方式进行扫描
⑤注解方式的属性注入
(1) @autowire 根据属性类型进行自动装配
(2) @Qualifier 根据名称进行注入 需要通@autowire一同使用
(3)@Resource 既可根据名称,也可根据名称注入
(4)@Value 可以注入普通类型属性
(5)完全注解开发
@Configuration(bakPages={“路径”,…}//作为配置类,替代 xml 配置文件