IOC&DI
IOC(Inversion of Control),其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源,作为回应呢,容器适时的返回资源,而应用了IOC之后,则是容器主动的将资源推送给它所管理的组件,组件所要做的仅仅是选择一种合适的方式来接受资源,这种行为也被称为查找的被动形式。
DI(Dependency Injection),IOC的另一种表达方式:即组件以一些预先定义好的方式,例如:setter方法,接受来自如容器的资源注入。
配置Bean
|
|
|
|
Bean配置方式 |
通过全类名(反射)、通过工厂方法(静态工厂方法&实例工厂方法)、FactoryBean |
|
IOC容器 |
BeanFactory、ApplicationContext |
|
依赖注入方式 |
属性注入、构造器注入 |
|
注入属性值细节 |
|
|
自动转配 |
|
|
Bean之间的关系 |
继承、依赖 |
|
Bean的作用域 |
singleton、prototype、web环境作用域 |
|
使用外部属性文件 |
|
|
spEL |
|
|
IOC容器中Bean的生命周期 |
|
|
Spring4.x新特性 |
泛型依赖注入 |
配置Bean-知识点1:Bean整体配置思路
整体配置思路就2个:基于XML文件的方式、基于注解的方式
id标识容器中的Bean,id必须是唯一的。
class是类的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参数的构造器。
配置Bean-知识点2:Spring容器
在Spring IOC容器读取Bean配置并创建Bean实例之前,必须对它进行实例化,只有在容器实例化之后,才可以从IOC容器里获取Bean实例并使用。
Spring提供了2种类型的IOC容器:
①BeanFactory:IOC容器的基本实现;
②ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口;
总结:BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,因此大多数场景都直接使用ApplicationContext,而不是底层的BeanFactory,无论哪种方式,其配置文件都是一样的。
配置Bean-知识点3:ApplicationContext
ApplicationContext的主要的实现类:
①ClassPathXmlApplicationContext:从类路径下加载配置文件;
②FileSystemXmlApplicationContext:从文件系统中加载配置文件;
注意事项:
①ConfigurableApplicationContext扩展了Application-
Context,新增2个方法:refresh()和close()方法,从而让ApplicationContext具有启动、刷新、关闭上下文的能力。
②ApplicationContext在初始化上下文时,就实例化所有单例的Bean。
③WebApplicationContext是专门为Web应用而准备的,允许从相对于web根目录的路径中完成初始化工作。
配置Bean-知识点4:依赖注入方式
3种依赖注入方式:属性注入、构造器注入、工厂方法注入(不推荐)。
①属性注入本质是通过setter方法注入Bean的属性值/依赖的对象。属性注入使用<property/>元素,使用name属性来指定Bean的属性名,value属性/<value/>子节点指定属性值。
这种属性注入是应用最广泛的注入方式。
当我把setName注释掉之后,系统报错,也从侧面证明其是用过setter方法来设置属性值的:
注意:
系统也能正常执行,这说明:Spring先获取name属性值,然后在属性值的基础上再添加set前缀,例如:name=”name22”,其实在Bean中并没有name22这个属性,但还是能执行成功,说明Spring关心的是setXXXX中的XXXX,而不是Bean中具体的某个属性名。
②构造方法注入是通过构造方法注入Bean的属性值/依赖对象,保证了Bean实例在实例化后就可以使用。构造器注入在<constructor-arg/>元素里声明属性name、index、type来说明参数值。
配置Bean-知识点5:字面值
在知识点4中学习了依赖注入方式,但是,在设置value属性时,则还有另外的知识点。
字面值:可用字符串表示的值,可以通过<value/>子标签或value属性进行注入,其中基本数据类型及其封装类、String等类型都可以采取字面值注入的方式,但是,如果字面值中包含特殊字符,则必须使用<![CDATA[字面值]]>把字面值包裹起来。
配置Bean-知识点6:引用其它Bean
要使Bean能够互相访问,就必须在Bean配置文件中指定对Bean的引用。在Bean的配置文件中,可以通过<ref/>标签或者ref属性来为Bean的属性或构造器参数指定对某个Bean的引用。
这种在属性或者构造器里包含的Bean的声明,这样的Bean称为内部Bean。内部Bean,不管有没有id属性,都无法被外部引用,只能被内部使用。
配置Bean-知识点7:null值和级联属性
针对null值,可以使用专用的<null/>标签为Bean的字符串或其他对象类型的属性来注入null值。
Spring也支持级联属性
这里在使用级联属性时,必须首先初始化属性car,然后才能为级联属性car.weight赋值,否则会出现异常。
配置Bean-知识点8:集合属性
Spring可以通过一组内置的XML标签,例如<list/>、<set/>、<map/>来配置集合属性。
初始化java.util.List类型的属性,需要使用<list/>标签,在标签内包含一些元素,而这些元素可以通过<value/>指定简单的常量值,也可以通过<ref/>指定对其他Bean的引用,也可以通过<bean/>指定内置Bean定义,也可以通过<null/>指定空元素,甚至可以内嵌其他集合。
初始化数组类型的属性跟List一样,都使用<list/>。
初始化java.util.Set类型的属性,需要使用<set/>标签,定义元素的方法与<list/>一样。
初始化java.util.Map类型的属性,需要使用<map/>标签定义,<map/>标签内部包含多个<entry/>子标签,每一个<entry/>子标签只能包含一个键盘和一个值;在<key/>标签里定义键,因为键和值的类型没有限制,因此可以自由地为键和值使用<value/>、<ref/>、<bean/>、<null/>元素,当然,也可以将Map的键和值作为<entry/>的属性来定义:简单常量使用key和value来定义,Bean引用通过key-ref和value-ref属性来定义。
初始化java.util.Properties类型的属性,可以使用<props/>标签来定义,该标签内部包含多个<prop>作为子标签,每个<prop>标签必须定义key属性。
配置Bean-知识点9:使用utility scheme定义集合
使用基本的集合标签来定义集合时,不能将集合作为独立的Bean定义,进而导致其他Bean无法引用该集合,所以无法在不同Bean之间共享集合,为了解决这个问题,可以使用util schema里的集合标签定义独立的集合Bean,需要注意的是,必须在<beans>根元素里添加util schema定义。
说白了就是通过util schema来把集合独立出来,作为一个共享资源来被其他Bean使用。
配置Bean-知识点10:使用p命名空间
为了简化XML文件的配置,越来越多的XML文件采用属性,而不是子元素来配置信息。因此,从Spring2.5开始引入了一个新的命名空间p,来通过<bean>元素属性的方式配置Bean的属性,因此,在使用p命名空间之后,基于XML的配置方式将进一步简化。
通过截图,我们可以返现,P命名空间可以大幅度减少开发人员代码量。
配置Bean-知识点11:自动装配
XML配置里的Bean自动装配,指的是Spring IOC容器可以自动装配Bean,这里的自动装配你可以理解为把XXX-ref=YYYY这种显示配置给删掉,然后IOC容器自己来完成这块工作,而我们需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式,autowire取值范围如下:
①byType根据类型自动装配:若IOC容器中有多个与目标Bean类型一致的Bean,这种情况下,Spring将无法判定哪个Bean最适合该属性,所以不能执行自动装配;
核心在于,假如当前Bean中定义了一个XXXX类型的变量,那么,自动装配的时候,就去查找class=”XXXX”的<bean/>,如果能找到且只有1个,则自动装配,如果没找到/IOC容器有2个及以上的类型匹配的Bean,则抛出异常。
②byName根据名称自动装配:必须将目标Bean的名称,与属性名设置的完全相同;
核心在于,假如当前Bean中定义了一个setXXXX的方法,那么,自动装配的时候,就去查找id=”XXXX”的<bean/>,如果能找到且只有1个,则自动装配,如果没找到/IOC容器有2个及以上的id匹配的Bean,则抛出异常。
③constructor通过构造器自动装配:当Bean中存在多个构造器时,这种自动装配方式将会很复杂,因此不推荐使用。
自动装配的缺点在于:
①在Bean配置文件里设置autowire属性进行自动装配将会装配Bean的所有属性,然而,如果只希望装配个别几个属性时,autowire则不够灵活。
②autowire属性,要么根据类型自动装配,要么根据名称自动装配,只能二选一,不能同时选择。
③实际开发中,自动装配用的很少,因为明确清晰的配置会减少不必要问题,进而减少为了解决这些问题而花费的时间、精力等。