Spring-IOC
基础概念
spring全家桶:spring,springmvc,spring boot,spring cloud
spring:出现在2020年左右,解决企业开发难度——减轻对项目模块之间的管理,类和类之间的管理,帮助开发人员创建对象,管理对象间的关系。spring核心技术ioc
、aop
,能实现模块之间、类之间的解耦合。
依赖:类A中使用类B的属性或方法,则称类A依赖类B。
bean的装配
基于XML配置文件:
借助构造器注入初始化bean
通过
<constructor-arg>
元素1
2
3
4
5
6
7
8
9
10
11构造注入:spring 调用类的有参构造方法,在创建对象时给属性赋值
构造注入使用constructor-arg标签,其标签属性:
name:表示构造方法的形参名
index:表示构造方法中的参数位置,参数从左到右是0、1、2的顺序
value:表示形参为简单类型时的参数的值,注:String类型变量也是简单类型
ref:表示形参为引用类型时的参数的值,应用bean的id
<bean id="sgtPeppers" class="cn.hznu.SgtPeppers">
<constructor-arg name="artist" value="Sgt. Pepper's Lonely Hearts Club Band"/>
<constructor-arg name="title" value="The Beatles"/>
</bean>通过
c-
命名空间
1 | 使用前需在xml顶部beans标签中声明命名空间 |
对于集合属性如List'、'Set
等其注入方式如下:
1 | <bean id="sgtPeppers" class="cn.hznu.SgtPeppers"> |
<constructor-arg>
元素比c-
命名空间比较:
- 前者比后者ml文件更加难读懂(书中这么写道,但个人而言觉得前者的可读性较好,但编写更麻烦);
- 有些事情只有前者能做,但是后者做不了,比如说后者无法完成装配集合功能。
通过设置属性setter
注:一定要有元素对应的
setter
方法,必须要有对应构造方法,如空构造
基本与构造器注入类似,对应关系为<property>
元素、p-
命名空间,具体使用参考下述案例:
1 | 基于<property>元素 |
对于命名空间无法注入集合的问题,存在下述解决方法:
1 | 包含命名空间 |
Spring util-
命名空间中的元素l
元素 | 描述 |
---|---|
util-constant |
引用某个类型的public static 域,并将其暴露为bean |
util-list |
创建一个java.util.List ,类型的bean ,其中包含值或引用 |
util-map |
创建一个java.util.Map ,类型的bean ,其中包含值或引用 |
util-properties |
创建一个java.util.Property ,类型的bean ,其中包含值或引用 |
util-prooerty-path |
引用bean 的属性(或内嵌属性),并将其暴露为bean |
util-set |
创建一个java.util.Set ,类型的bean ,其中包含值或引用 |
缺点:
- 在bean的声明中,
<bean id="cdPlayer" class="cn.hznu.CDPlayer"/>
,由于类型(即Class)由字符串声明,该方式的声明并不能从编译器的类型检查中受益,问题:将Class名重命名后,会发生什么?
处理自动装配的歧义性
问题说明
一个最简单的案例如下:
1 | // 接口 |
很明显,在测试类中要通过@Autowired
注解自动注入,Spring显然不能明确到低要注入哪一个bean,因此会产生歧义。
以下为几种解决方法。
解决方法
1、创建首选的bean
在创建bean时利用 @Primary
注解标识为首选,具体代码如下:
1 | // 1、JavaCongid中显示声明bean时,加上@Primary注解,标识其为首选 |
1 | <!-- xml文件声明bean时 --> |
注:但这里并不限制设定首选bean的个数,所以可能还会产生歧义。
2、限制自动装配的bean
通过@Qualifier
注解设定注入的bean的限定符,即可对应唯一的bean,从而解决歧义问题,如下:
1 |
|
注:限定符与bean的id的区分(二者不是同一概念),在未主动声明bean的限定符时,限定符与bean的id相等,但仅限于字符串的相等。
创建自定义的限定符
通过@Qualifier
注解在声明bean的时候自定义标识符,同上述 @Primary
的用法,不再赘述。
注:一般自定义限定符时,最佳实践是为bean选择特征性或描述性的术语,而不是随意指定名字。
如:
1 |
|
但这里发现一个很奇怪的问题,当对bean自定义限定符之后,默认限定符依旧可用。
测试后发现,自动注入时首先参照自定义限定符,若给定的限定符不存在bean与之对应,则会向下查找bean id相同的bean然后注入。
测试代码:
1 | // Java配置部分 |
注:在容器中存在多个相同特性的bean的情况下,这种方式也会失效。最终的解决方法是使用自定义的限定注解,具体参照《Spring in Action 4》P82.
bean的作用域
默认情况下,Spring应用上下文中所有的bean都是作为以单例(Singleton)的形式创建的。
Spring定义了多种作用域,具体如下:
模式 | 描述 |
---|---|
单例(Singleton) | 在整个应用中,只创建一个bean实例。 |
原型(Prototype) | 每次注入或者通过Spring应用上下文获取时,都会创建一个新的实例。 |
会话(Session) | 在Web应用中,为每个会话创建一个bean实例。 |
请求(request) | 在Web应用中,为每个请求创建一个bean实例。 |
1、单例(Singleton)
默认状态下就是这个模式,测试代码如下:
1 | // 实例类 |
2、原型(Prototype)
就如图表中所描述,具体测试如下,配置类、测试类相同一下代码不重复贴了:
1 |
|
1 | <!-- xml配置文件中的写法 --> |
注:每创建一次上下文,则会将所有的单例模式的类重新创建bean,对于原型模式下的类只有用到时才会创建。
案例:
1 | // 其中TestClass是原型模式,而TestClass01则是单例模式,而定义中只包含记录类实例个数的静态变量cnt |
3、使用会话和请求作用域
看到Web部分再填坑。
运行时值注入
1、注入外部的值
1 | // 配置类 |
2、通过XML配置文件引入Property文件
1 |
|