1Spring概述
1.1Spring概述
1.spring是一个开源框架。
2.spring为简化企业级开发而生,使用spring,Javabean就可以实现很多以前要考EJB才能实现的功能。同样的功能,在EJB中要通过繁琐的配置和复杂的代码才能实现,而在spring中去表现的优雅和简介。
3.spring是一个IOC(DI)和AOP容器框架。
4.spring的优良特性
- 非侵入式:基于spring开发的应用中的对象可以不依赖与spring的API
- 依赖注入:DI--Dependency Injection ,控制反转IOC最简单的实现
- 面向切面编程:Aspect Oriented Programming --AOP
- 容器:spring是一个容器,因为它包含并且管理应用对象的生命周期
- 组件化:spring实现了使用简单的配置组件组成一个复杂的应用,在spring中可以使用XML方式和java注解组合这些对象
- 一站式:在IOC和AOP的基础上可以整合各种企业应用的开原框架和优秀的第三方类库(实际上spring自身也提供了表述层的springMVC和持久层的springJDBC)
- spring模块
1.2
安装
Spring
插件【了解】
1)
插件包:
springsource-tool-suite-3.4.0.RELEASE-e4.3.1-updatesite.zip
1.3
搭建
Spring
运行时环境
1)
加入
JAR
包
① Spring
自身
JAR
包:
spring-framework-4.0.0.RELEASE\libs
目录下
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
② commons-logging-1.1.1.jar
2)
在
Spring Tool Suite
工具中通过如下步骤创建
Spring
的配置文件
① File->New->Spring Bean Configuration File
②
为文件取名字 例如:
applicationContext.xml
1.4 HelloWorld
1)
目标:使用
Spring
创建对象,为属性赋值
2)
创建
Student
类
3)
创建
Spring
配置文件
<!--
使用
bean
元素定义一个由
IOC
容器创建的对象
-->
<!-- class
属性指定用于创建
bean
的全类名
-->
<!-- id
属性指定用于引用
bean
实例的标识
-->
<
bean
id
=
"student"
class
=
"com.atguigu.helloworld.bean.Student"
>
<!--
使用
property
子元素为
bean
的属性赋值
-->
<
property
name
=
"studentId"
value
=
"1001"
/>
<
property
name
=
"stuName"
value
=
"Tom2015"
/>
<
property
name
=
"age"
value
=
"20"
/>
</
bean
>
4)
测试:通过
Spring
的
IOC
容器创建
Student
类实例
/1.
创建
IOC
容器对象
ApplicationContext iocContainer =
new
ClassPathXmlApplicationContext(
"helloworld.xml"
);
//2.
根据
id
值获取
bean
实例对象
Student student = (Student) iocContainer.getBean(
"student"
)
2.1 IOC 和 DI
2.1.1 IOC(Inversion of Control):反转控制
在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需 要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式, 增加了学习成本,同时降低了开发效率。
反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取 方向——
改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创 建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发 的效率。这种行为也称为查找的
被动形式
。
2.1.2 DI(Dependency Injection):依赖注入
IOC
的另一种表述方式:即组件以一些预先定义好的方式
(
例如:
setter
方法
)
接受
来自于容器的资源注入。相对于
IOC
而言,这种表述更直接。
2.1.3 IOC 容器在 Spring 中的实现
1
)在通过
IOC
容器读取
Bean
的实例之前,需要先将
IOC
容器本身实例化。
2
)
Spring
提供了
IOC
容器的两种实现方式
① BeanFactory
:
IOC
容器的基本实现,是
Spring
内部的基础设施,是面向
Spring
本身的,不是提供给开发人员使用的。
② ApplicationContext
:
BeanFactory
的子接口,提供了更多高级特性。面向
Spring
的 使 用 者 , 几 乎 所 有 场 合 都 使 用
ApplicationContext
而 不 是 底 层 的
BeanFactory
。
2.1.4 ApplicationContext 的主要实现类
1)
ClassPathXmlApplicationContext
:对应类路径下的
XML
格式的配置文件
2)
FileSystemXmlApplicationContext
:对应文件系统中的
XML
格式的配置文件
3)
在初始化时就创建单例的
bean
,也可以通过配置的方式指定创建的
Bean
是多实例的。
2.1.5 ConfigurableApplicationContext
1)
是
ApplicationContext
的子接口,包含一些扩展方法
2)
refresh()
和
close()
让
ApplicationContext
具有启动、关闭和刷新上下文的能力。
2.1.6 WebApplicationContext
1)
专门为
WEB
应用而准备的,它允许从相对于
WEB
根目录的路径中完成初始化工作
2.2 通过类型获取 bean
1)
从
IOC
容器中获取
bean
时,除了通过
id
值获取,还可以通过
bean
的类型获取。但如
果同一个类型的
bean
在
XML
文件中配置了多个,则获取时会抛出异常,所以同一个类
型的
bean
在容器中必须是唯一的
HelloWorld helloWorld = cxt.getBean(HelloWorld. class);
2)
或者可以使用另外一个重载的方法,同时指定
bean
的
id
值和类型
HelloWorld helloWorld = cxt.getBean(“helloWorld”,HelloWorld. class)
2.3
给
bean
的属性赋值
2.3.1
依赖注入的方式
1.
通过
bean
的
setXxx()
方法赋值
Hello World
中使用的就是这种方式
2.
通过
bean
的构造器赋值
1)
Spring
自动匹配合适的构造器
<
bean
id
=
"book"
class
=
"com.atguigu.spring.bean.Book"
>
<
constructor-arg
value
=
"10010"
/>
<
constructor-arg
value
=
"Book01"
/>
<
constructor-arg
value
=
"Author01"
/>
<
constructor-arg
value
=
"20.2"
/>
</
bean
>
2)
通过索引值指定参数位置
<
bean
id
=
"book"
class
=
"com.atguigu.spring.bean.Book"
>
<
constructor-arg
value
=
"10010"
index
=
"0"
/>
<
constructor-arg
value
=
"Book01"
index
=
"1"
/>
<
constructor-arg
value
=
"Author01"
index
=
"2"
/>
<
constructor-arg
value
=
"20.2"
index
=
"3"
/>
</
bean
>
3)
通过类型区分重载的构造器
<
bean
id
=
"book"
class
=
"com.atguigu.spring.bean.Book"
>
<
constructor-arg
value
=
"10010"
index
=
"0"
type
=
"
java.lang.Integer"
/>
<
constructor-arg
value
=
"Book01"
index
=
"1"
type
=
"
java.lang.String"
/>
<
constructor-arg
value
=
"Author01"
index
=
"2"
type
=
"
java.lang.String"
/>
<
constructor-arg
value
=
"20.2"
index
=
"3"
type
=
"
java.lang.Double"
/>
</
bean
>
2.3.2 p
名称空间
为了简化
XML
文件的配置,越来越多的
XML
文件采用属性而非子元素配置信息。
Spring
从
2.5
版本开始引入了一个新的
p
命名空间,可以通过
<bean>
元素属性的方式配置
Bean
的属性。
使用
p
命名空间后,基于
XML
的配置方式将进一步简化。
<
bean
id
=
"studentSuper"
class
=
"com.atguigu.helloworld.bean.Student"
p:studentId
=
"2002"
p:stuName
=
"Jerry2016"
p:age
=
"18"
/>
2.3.3
可以使用的值
1.
字面量
1)
可以使用字符串表示的值,可以通过
value
属性或
value
子节点的方式指定
2)
基本数据类型及其封装类、
String
等类型都可以采取字面值注入的方式
3)
若字面值中包含特殊字符,可以使用
<![CDATA[]]>
把字面值包裹起来
2. null
值
<
bean
class
=
"com.atguigu.spring.bean.Book"
id
=
"bookNull"
>
<
property
name
=
"bookId"
value
=
"2000"
/>
<
property
name
=
"bookName"
>
<
null
/>
</
property
>
<
property
name
=
"author"
value
=
"nullAuthor"
/>
<
property
name
=
"price"
value
=
"50"
/>
</
bean
>
3.
给
bean
的级联属性赋值
<bean id="action" class="com.atguigu.spring.ref.Action">
<property name="service" ref="service"/>
<!--
设置级联属性
(
了解
) -->
<property name="service.dao.dataSource" value="DBCP"/>
</bean>
4.
外部已声明的
bean
<
bean
id
=
"shop"
class
=
"com.atguigu.spring.bean.Shop"
>
<
property
name
=
"book"
ref
=
"book"
/>
</
bean
>
5.
内部
bean
当
bean
实例仅仅给一个特定的属性使用时,可以将其声明为内部
bean。内部bean 声明直接包含在<property>或<constructor-arg>元素里,不需要设置任何 id或 name 属性内部 bean 不能使用在任何其他地方
<
bean
id
=
"shop2"
class
=
"com.atguigu.spring.bean.Shop"
>
<
property
name
=
"book"
>
<
bean
class
=
"com.atguigu.spring.bean.Book"
>
<
property
name
=
"bookId"
value
=
"1000"
/>
<
property
name
=
"bookName"
value
=
"innerBook"
/>
<
property
name
=
"author"
value
=
"innerAuthor"
/>
<
property
name
=
"price"
value
=
"50"
/>
</
bean
>
</
property
>
</
bean
>
2.4
集合属性
在
Spring
中可以通过一组内置的
XML
标签来配置集合属性,例如:
<list>
,
<set>
或
<map>
。
2.4.1
数组和
List
配置
java.util.List
类型的属性,需要指定
<list>
标签,在标签里包含一些元素。这些标签
可以通过
<value>
指定简单的常量值,通过
<ref>
指定对其他
Bean
的引用。通过
<bean>
指定内置
bean
定义。通过
<null/>
指定空元素。甚至可以内嵌其他集合。
数组的定义和
List
一样,都使用
<list>
元素。
配置
java.util.Set
需要使用
<set>
标签,定义的方法与
List
一样。
<
bean
id
=
"shop"
class
=
"com.atguigu.spring.bean.Shop"
>
<
property
name
=
"categoryList"
>
<!--
以字面量为值的
List
集合
-->
<
list
>
<
value
>
历史
</
value
>
<
value
>
军事
</
value
>
</
list
>
</
property
>
<
property
name
=
"bookList"
>
<!--
以
bean
的引用为值的
List
集合
-->
<
list
>
<
ref
bean
=
"book01"
/>
<
ref
bean
=
"book02"
/>
</
list
>
</
property
>
</
bean
>
2.4.2 Map
Java.util.Map
通过
<map>
标签定义,
<map>
标签里可以使用多个
<entry>
作为子标签。每
个条目包含一个键和一个值。
必须在
<key>
标签里定义键。
因为键和值的类型没有限制,所以可以自由地为它们指定
<value>
、
<ref>
、
<bean>
或
<null/>
元素。
可以将
Map
的键和值作为
<entry>
的属性定义:简单常量使用
key
和
value
来定义;
bean
引用通过
key-ref
和
value-ref
属性定义。
<
bean
id
=
"cup"
class
=
"com.atguigu.spring.bean.Cup"
>
<
property
name
=
"bookMap"
>
<
map
>
<
entry
>
<
key
>
<
value
>
bookKey01
</
value
>
</
key
>
<
ref
bean
=
"book01"
/>
</
entry
>
<
entry
>
<
key
>
<
value
>
bookKey02
</
value
>
</
key
>
<
ref
bean
=
"book02"
/>
</
entry
>
</
map
>
</
property
>
</
bean
>
2.4.3
集合类型的
bean
如果只能将集合对象配置在某个
bean
内部,则这个集合的配置将不能重用。我们需要
将集合
bean
的配置拿到外面,供其他
bean
引用。
配置集合类型的
bean
需要引入
util
名称空间
<
util:list
id
=
"bookList"
>
<
ref
bean
=
"book01"
/>
<
ref
bean
=
"book02"
/>
<
ref
bean
=
"book03"
/>
<
ref
bean
=
"book04"
/
<
ref
bean
=
"book05"
/>
</
util:list
>
<
util:list
id
=
"categoryList"
>
<
value
>
编程
</
value
>
<
value
>
极客
</
value
>
<
value
>
相声
</
value
>
<
value
>
评书
</
value
>
</
util:list
>
2.5 FactoryBean
2.5.1 FactoryBean
Spring
中有两种类型的
bean
,一种是普通
bean
,另一种是工厂
bean
,即
FactoryBean
。 工厂 bean
跟普通
bean
不同,其返回的对象不是指定类的一个实例,其返回的是该工 厂 bean
的
getObject
方法所返回的对象。 工厂 bean
必须实
org.springframework.beans.factory.FactoryBean
接口。
<
bean
id
=
"product"
class
=
"com.atguigu.spring.bean.ProductFactory"
>
<
property
name
=
"productName"
value
=
"Mp3"
/>
</
bean
>
2.6 bean
的高级配置
2.6.1
配置信息的继承
1.
背景
查看下面两个
Employee
的配置,其中
dept
属性是重复的
<
bean
id
=
"dept"
class
=
"com.atguigu.parent.bean.Department"
>
<
property
name
=
"deptId"
value
=
"100"
/>
<
property
name
=
"deptName"
value
=
"IT"
/>
</
bean
>
<
bean
id
=
"emp01"
class
=
"com.atguigu.parent.bean.Employee"
>
<
property
name
=
"empId"
value
=
"1001"
/>
<
property
name
=
"empName"
value
=
"Tom"
/>
<
property
name
=
"age"
value
=
"20"
/>
<!--
重复的属性值
-->
<
property
name
=
"dept"
ref
=
"dept"
/>
</
bean
>
<
bean
id
=
"emp02"
class
=
"com.atguigu.parent.bean.Employee"
>
<
property
name
=
"empId"
value
=
"1002"
/>
<
property
name
=
"empName"
value
=
"Jerry"
/>
<
property
name
=
"age"
value
=
"25"
/>
<!--
重复的属性值
-->
<
property
name
=
"dept"
ref
=
"dept"
/>
<!--
以
emp01
作为父
bean
,继承后可以省略公共属性值的配置
-->
<
bean
id
=
"emp02"
parent
=
"emp01"
>
<
property
name
=
"empId"
value
=
"1002"
/>
<
property
name
=
"empName"
value
=
"Jerry"
/>
<
property
name
=
"age"
value
=
"25"
/>
</
bean
>
Spring
允许继承
bean
的配置,被继承的
bean
称为父
bean
。继承这个父
bean
的
bean 称为子 bean 子 bean
从父
bean
中继承配置,包括
bean
的属性配置 子 bean
也可以覆盖从父
bean
继承过来的配置
3.
补充说明
父
bean
可以作为配置模板,也可以作为
bean
实例。若只想把父
bean
作为模板,可以
设置
<bean>
的
abstract
属性为
true
,这样
Spring
将不会实例化这个
bean
如果一个
bean
的
class
属性没有指定,则必须是抽象
bean
并不是
<bean>
元素里的所有属性都会被继承。比如:
autowire
,
abstract
等。
也可以忽略父
bean
的
class
属性,让子
bean
指定自己的类,而共享相同的属性配置。 但
此时
abstract
必须设为
true
。
2.6.2 bean
之间的依赖
有的时候创建一个
bean
的时候需要保证另外一个
bean 也被创建,这时我们称前面的bean 对后面的 bean 有依赖。例如:要求创建 Employee 对象的时候必须创建 Department。这里需要注意的是依赖关系不等于引用关系,Employee 即使依赖 Department 也可以不引用它。
<
bean
id
=
"emp03"
class
=
"com.atguigu.parent.bean.Employee"
depends-on
=
"dept"
>
<
property
name
=
"empId"
value
=
"1003"
/>
<
property
name
=
"empName"
value
=
"Kate"
/>
<
property
name
=
"age"
value
=
"21"
/>
</
2.7 bean
的作用域
★
在
Spring
中,可以在
<bean>
元素的
scope
属性里设置
bean
的作用域,以决定这个
bean
是单实例的还是多实例的。
默认情况下,
Spring
只为每个在
IOC
容器里声明的
bean
创建唯一一个实例,整个
IOC
容器范围内都能共享该实例:所有后续的
getBean()
调用和
bean
引用都将返回这个唯一的
bean
实例。该作用域被称为
singleton
,它是所有
bean 的默认作用域。
当
bean
的作用域为单例时,
Spring
会在
IOC
容器对象创建时就创建
bean
的对象实例。
而当
bean
的作用域为
prototype
时,
IOC
容器在获取
bean
的实例时创建
bean
的实例对象。
2.8 bean
的生命周期
1)
Spring IOC
容器可以管理
bean
的生命周期,
Spring
允许在
bean
生命周期内特定的时间
点执行指定的任务。
2)
Spring IOC
容器对
bean
的生命周期进行管理的过程:
①
通过构造器或工厂方法创建
bean
实例
②
为
bean
的属性设置值和对其他
bean
的引用
③
调用
bean
的初始化方法
④ bean
可以使用了
⑤
当容器关闭时,调用
bean
的销毁方法
3)
在配置
bean
时,通过
init-method
和
destroy-method
属性为
bean
指定初始化和销毁
方法
4)
bean
的后置处理器
① bean
后置处理器允许在调用
初始化方法前后
对
bean
进行额外的处理
② bean
后置处理器对
IOC
容器里的所有
bean
实例逐一处理,而非单一实例。其典型
应用是:检查
bean
属性的正确性或根据特定的标准更改
bean
的属性。
③ bean
后置处理器时需要实现接口:
org.springframework.beans.factory.config.BeanPostProcessor
。在初始化方法被调用前
后,
Spring
将把每个
bean
实例分别传递给上述接口的以下两个方法:
●
postProcessBeforeInitialization(Object, String)
●
postProcessAfterInitialization(Object, String)
5)
添加
bean
后置处理器后
bean
的生命周期
①
通过构造器或工厂方法
创建
bean
实例
②
为
bean
的
属性设置值
和对其他
bean
的引用
③
将
bean
实例传递给
bean
后置处理器的
postProcessBeforeInitialization()
方法
④
调用
bean
的
初始化
方法
⑤
将
bean
实例传递给
bean
后置处理器的
postProcessAfterInitialization()
方法
⑥bean
可以使用了
⑦
当容器关闭时调用
bean
的
销毁方法
2.9
引用外部属性文件
当
bean
的配置信息逐渐增多时,查找和修改一些
bean
的配置信息就变得愈加困难。这
时可以将一部分信息提取到
bean
配置文件的外部,以
properties
格式的属性文件保存起来,
同时在
bean
的配置文件中引用
properties
属性文件中的内容,从而实现一部分属性值在发
生变化时仅修改
properties
属性文件即可。这种技术多用于连接数据库的基本信息的配置。
2.9.1
直接配置
<!--
直接配置
-->
<
bean
id
=
"dataSource"
class
=
"com.mchange.v2.c3p0.ComboPooledDataSource"
>
<
property
name
=
"user"
value
=
"root"
/>
<
property
name
=
"password"
value
=
"root"
/>
<
property
name
=
"
jdbcUrl"
value
=
"
jdbc:mysql:///test"
/>
<
property
name
=
"driverClass"
value
=
"com.mysql.jdbc.Driver"
/>
</
bean
>
2.9.2
使用外部的属性文件
1.
创建
properties
属性文件
prop.userName=
root
prop.password=
root
prop.url=
jdbc:mysql:///test
prop.driverClass=
com.mysql.jdbc.Driver
<!--
指定
properties
属性文件的位置
-->
<!-- classpath:xxx
表示属性文件位于类路径下
-->
<
context:property-placeholder
location
=
"classpath:jdbc.properties"
/>
4.
从
properties
属性文件中引入属性值
<!--
从
properties
属性文件中引入属性值
-->
<
bean
id
=
"dataSource"
class
=
"com.mchange.v2.c3p0.ComboPooledDataSource"
>
<
property
name
=
"user"
value
=
"
${prop.userName}
"
/>
<
property
name
=
"password"
value
=
"
${prop.password}
"
/>
<
property
name
=
"
jdbcUrl"
value
=
"
${prop.url}
"
/>
<
property
name
=
"driverClass"
value
=
"
${prop.driverClass}
"
/>
</
bean
>
2.10
自动装配
2.10.1
自动装配的概念
1)
手动装配:以
value
或
ref
的方式
明确指定属性值
都是手动装配。
2)
自动装配:根据指定的装配规则,
不需要明确指定
,
Spring
自动
将匹配的属性值
注入
bean
中。
2.10.2
装配模式
1)
根据
类型
自动装配:将类型匹配的
bean
作为属性注入到另一个
bean
中。若
IOC
容器中
有多个与目标
bean
类型一致的
bean
,
Spring
将无法判定哪个
bean
最合适该属性,所
以不能执行自动装配
2)
根据
名称
自动装配:必须将目标
bean
的名称和属性名设置的完全相同
3)
通过构造器自动装配:当
bean
中存在多个构造器时,此种自动装配方式将会很复杂。
不推荐使用。
2.10.3
选用建议
相对于使用注解的方式实现的自动装配,在
XML
文档中进行的自动装配略显笨拙,在
项目中更多的使用注解的方式实现。
2.11 SpEL
2.11.1
简介
Spring Expression Language
,
Spring
表达式语言,简称
SpEL
。支持运行时查询并可以操
作对象图。
和
JSP
页面上的
EL
表达式、
Struts2
中用到的
OGNL
表达式一样,
SpEL
根据
JavaBean
风
格的
getXxx()
、
setXxx()
方法定义的属性
访问对象图,
完全符合我们熟悉的操作习惯
。
2.11.2
基本语法
SpEL
使用
#{…}
作为定界符,所有在大框号中的字符都将被认为是
SpEL
表达式。
2.11.3
使用字面量
1)
整数:
<property name="count" value="
#{5}
"/>
2)
小数:
<property name="frequency" value="
#{89.7}
"/>
3)
科学计数法:
<property name="capacity" value="
#{1e4}
"/>
4) String
类型的字面量可以使用单引号或者双引号作为字符串的定界符号
<property name="name" value=
"#{'Chuck'}"
/>
<property name="name" value=
'#{"Chuck"}'
/>
5) Boolean
:
<property name="enabled" value="
#{false}
"/>
2.11.4
引用其他
bean
<
bean
id
=
"emp04"
class
=
"com.atguigu.parent.bean.Employee"
>
<
property
name
=
"empId"
value
=
"1003"
/>
<
property
name
=
"empName"
value
=
"Kate"
/>
<
property
name
=
"age"
value
=
"21"
/>
<
property
name
=
"detp"
value
=
"
#{dept}
"
/>
</
bean
2.11.5
引用其他
bean
的属性值作为自己某个属性的值
<
bean
id
=
"emp05"
class
=
"com.atguigu.parent.bean.Employee"
>
<
property
name
=
"empId"
value
=
"1003"
/>
<
property
name
=
"empName"
value
=
"Kate"
/>
<
property
name
=
"age"
value
=
"21"
/>
<
property
name
=
"deptName"
value
=
"
#{dept.deptName}
"
/>
</
bean
>
<!--
创建一个对象,在
SpEL
表达式中调用这个对象的方法
-->
<
bean
id
=
"salaryGenerator"
class
=
"com.atguigu.spel.bean.SalaryGenerator"
/>
<
bean
id
=
"employee"
class
=
"com.atguigu.spel.bean.Employee"
>
<!--
通过对象方法的返回值为属性赋值
-->
<
property
name
=
"salayOfYear"
value
=
"
#{salaryGenerator.getSalaryOfYear(5000)}
"
/>
</
bean
>
<
bean
id
=
"employee"
class
=
"com.atguigu.spel.bean.Employee"
>
<!--
在
SpEL
表达式中调用类的静态方法
-->
<
property
name
=
"circle"
value
=
"
#{T(java.lang.Math).PI*20}
"
/>
</
bean
>
2.11.8
运算符
1)
算术运算符:
+
、
-
、
*
、
/
、
%
、
^
2)
字符串连接:
+
3) 比较运算符:<
、
>
、
==
、
<=
、
>=
、
lt
、
gt
、
eq
、
le
、
ge
4)
逻辑运算符:
and, or, not, |
5)
三目运算符:判断条件
?
判断结果为
true
时的取值
:
判断结果为
false
时的取值
6)
正则表达式:
matches
2.12
通过注解配置
bean
2.12.1
概述
相对于
XML
方式而言,通过注解的方式配置
bean
更加简洁和优雅,而且和
MVC
组件
化开发的理念十分契合,是开发中常用的使用方式。
2.12.2
使用注解标识组件
1)
普通组件:
@Component
标识一个受
Spring IOC
容器管理的组件
2)
持久化层组件:
@Repository
标识一个受
Spring IOC
容器管理的持久化层组件
3)
业务逻辑层组件:
@Service
标识一个受
Spring IOC
容器管理的业务逻辑层组件
4)
表述层控制器组件:
@Controller
标识一个受
Spring IOC
容器管理的表述层控制器组件
5)
组件命名规则
①
默认情况:使用组件的简单类名首字母小写后得到的字符串作为
bean
的
id
②
使用组件注解的
value
属性指定
bean
的
id
注意:事实上
Spring
并没有能力识别一个组件到底是不是它所标记的类型,即使将
@Respository
注解用在一个表述层控制器组件上面也不会产生任何错误,所以
@Respository
、
@Service
、
@Controller
这几个注解仅仅是为了让开发人员自己
明确
当前的组件扮演的角色。
2.12.3
扫描组件
组件被上述注解标识后还需要通过
Spring
进行扫描才能够侦测到。
1)
指定被扫描的
package
<
context:component-scan
base-package
=
"com.atguigu.component"
/>
2)
详细说明
①
base-package
属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包及其 子包中的所有类。
②
当需要扫描多个包时可以使用逗号分隔。
③
如果仅希望扫描特定的类而非基包下的所有类,可使用
resource-pattern
属性过滤特 定的类,示例:
<
context:component-scan
base-package
=
"com.atguigu.component"
resource-pattern
=
"autowire/*.class"
/
④
包含与排除
●
<context:include-filter>
子节点表示要包含的目标类
注意:通常需要与
use-default-filters
属性配合使用才能够达到
“
仅包含某些
组件
”
这样的效果。即:通过将
use-default-filters
属性设置为
false
,
禁用默认过滤器,然后扫描的就只是
include-filter
中的规则指定的
组件了。
●
<context:exclude-filter>
子节点表示要排除在外的目标类
●
component-scan
下可以拥有若干个
include-filter
和
exclude-filter
子节点
●
过滤表达式
2.12.4
组件装配
1)
需求
Controller
组件中往往需要用到
Service
组件的实例,
Service
组件中往往需要用到
Repository
组件的实例。
Spring
可以通过注解的方式帮我们实现属性的装配。
2)
实现依据
在指定要扫描的包时,
<context:component-scan>
元素会自动注册一个
bean
的后置处
理器:
AutowiredAnnotationBeanPostProcessor
的实例。该后置处理器可以自动装配标记
了
@Autowired
、
@Resource
或
@Inject
注解的属性。
3)
@Autowired
注解
①
根据类型实现自动装配。
②
构造器、普通字段
(
即使是非
public)
、一切具有参数的方法都可以应用
@Autowired
注解
③
默认情况下,所有使用
@Autowired
注解的属性都需要被设置。当
Spring
找不到匹
配的
bean
装配属性时,会抛出异常。
④
若某一属性允许不被设置,可以设置
@Autowired
注解的
required
属性为
false
⑤
默认情况下,当
IOC
容器里存在多个类型兼容的
bean
时,
Spring
会尝试匹配
bean
的
id
值是否与变量名相同,如果相同则进行装配。如果
bean
的
id
值不相同,通
过类
型的自动装配将无法工作。此时可以在
@Qualifier
注解里提供
bean
的名称。
Spring
甚至允许在方法的形参上标注
@Qualifiter
注解以指定注入
bean
的名称。
⑥@Autowired
注解也可以应用在数组类型的属性上,此时
Spring
将会把所有匹配的
bean
进行自动装配。
⑦@Autowired
注解也可以应用在集合属性上,此时
Spring
读取该集合的类型信息,
然后自动装配所有与之兼容的
bean
。
⑧@Autowired
注解用在
java.util.Map
上时,若该
Map
的键值为
String
,那么
Spring
将自动装配与值类型兼容的
bean
作为值,并以
bean
的
id
值作为键。
4)
@Resource
@Resource
注解要求提供一个
bean
名称的属性,若该属性为空,则自动采用标注处的
变量或方法名作为
bean
的名称。
5)
@Inject
@Inject
和
@Autowired
注解一样也是按类型注入匹配的
bean
,但没有
reqired
属性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)