一、bean配置的要点
1、配置形式:基于 XML 文件的方式;基于注解的方式
2、Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean
3、IOC 容器 BeanFactory & ApplicationContext 概述
4、依赖注入的方式:属性注入;构造器注入
5、注入属性值细节
6、自动转配
7、bean 之间的关系:继承;依赖
8、bean 的作用域:singleton;prototype;WEB 环境作用域
9、使用外部属性文件
10、spEL
11、IOC 容器中 Bean 的生命周期
12、Spring 4.x 新特性:泛型依赖注入
二、IoC容器——BeanFactory & ApplicationContext
1、容器是spring的核心,使IoC管理所有和组件
2、spring的两种容器:a、BeanFactoy b、ApplicationContext
3、BeanFactory:BeanFactory使用延迟加载所有的Bean,为了从BeanhFactory得到一个Bean,只要调用getBean()方法,就能获得Bean
4、ApplicationContext:
- 提供文本信息解析,支持I18N(页面国际化)
- 提供载入文件资源的通用方法
- 向注册为监听器的Bean发送事件
- ApplicationContext接口扩展BeanFactory接口
- ApplicationContext提供附加功能
5、ApplicationContext的三个实现类:
a、ClassPathXmlApplication:把上下文文件当成类路径资源
b、FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息
c、XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息
几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
ApplicationContext 在初始化上下文时就实例化所有单例的 Bean。
调用getBean()方法从容器中获取Bean对象
三、依赖注入的方式——属性注入&构造器注入
Spring 支持 3 种依赖注入的方式:属性注入、构造器注入、工厂方法注入(很少使用,不推荐)
(一)属性注入
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
属性注入使用 <property>
元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value>
子节点指定属性值
属性注入是实际应用中最常用的注入方式
public class HelloWorld {
String name;
public void setName(String name) {
this.name = name;
}
}
<!-- 使用属性注入方式来配置bean属性 -->
<bean id="helloWorld" class="com.aiguigu.spring.beans.HelloWorld" >
<property name="name" value="Spring"></property>
</bean>
(二)构造器注入
构造器注入在 元素里声明属性, 中没有 name 属性
///Car类构造函数
public Car(String brand, String corp,double price) {
super();
this.brand = brand;
this.price = price;
this.corp = corp;
}
按索引:
按类型匹配:
(三)属性注入的细节
字面值:
* <property name="name" value=字面值>
* 用字符串表示,基本数据类型、对象、封装类都可以用字面值注入
* 特殊字符 :用<![CDATA[字面值]]>
把字面值包裹起来
引用其他Bean:
* 通过 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用.
- 在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean
内部 Bean 声明直接包含在<property> 或 <constructor-arg>
元素里, 不需要设置任何 id 或 name 属性
级联属性:
在 Spring中可以通过一组内置的 xml 标签(例如: <list>, <set> 或 <map>
) 来配置集合属性.
配置 java.util.List 类型的属性, 需要指定 <list>
标签
配置 java.util.Set 类型的属性, 需要使用 <set>
标签
Java.util.Map 通过 <map>
标签定义, <map>
标签里可以使用多个 <entry>
作为子标签. 每个条目包含一个键和一个值.
java.util.Properties使用 <props>
定义, 该标签使用多个 <prop>
作为子标签. 每个 <prop>
标签必须定义 key 属性
使用基本的集合标签定义集合时, 不能将集合作为独立的 Bean 定义, 导致其他 Bean 无法引用该集合, 所以无法在不同 Bean 之间共享集合.
可以使用 util schema 里的集合标签定义独立的集合 Bean. 需要注意的是, 必须在 <beans>
根元素里添加 util schema
定义.
记得在xml的namespace中添加util
P命名空间:
使用 p 命名空间后,基于 XML 的配置方式将进一步简化
记得在xml的namespace中添加p
## (四)自动装配
Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 的 autowire 属性里指定自动装配的模式
byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配.
byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同.
constructor(通过构造器自动装配): 当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用
autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之.
四、bean 之间的关系——继承&依赖
继承
Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean
子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置,子 Bean 也可以覆盖从父 Bean 继承过来的配置。
父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置<bean>
的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean。
并不是 <bean>
元素里的所有属性都会被继承. 比如: autowire, abstract 等。
.
也可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true。
依赖
Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好
如果前置依赖于多个 Bean,则可以通过逗号,空格或的方式配置 Bean 的名称
五、Bean的作用域——singleton;prototype;WEB 环境作用域
singleton
在 Spring 中, 可以在 <bean>
元素的 scope
属性里设置 Bean 的作用域.
是==单例模式==,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例;
注意这里的Spring singleton模式是默认缺省的==饿汉模式== 启容器时(即实例化容器时),为所有spring配置文件中定义的bean都生成一个实例。
可是这样做会导致系统的开销比较大,为了不占用过大的资源或者是减少开销,一般我会在spring中添加缺省文件:
<beans default-lazy-init="true">
将系统默认的饿汉模式转换成懒汉模式,也就是在第一次请求的时候我们才生成一个实例。
prototype
原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。
prototype作用域Bean的创建、销毁代价比较大。
request ,session
用在web
六、Spring管理Bean生命周期
初始化方法和销毁方法
Spring IOC 容器对 Bean 的生命周期进行管理的过程:
* 通过构造器或工厂方法创建 Bean 实例
* 为 Bean 的属性设置值和对其他 Bean 的引用
* 调用 Bean 的初始化方法init-method()
* Bean 可以使用了
* 当容器关闭时, 调用 Bean 的销毁方法destroy-method()
在 Bean 的关闭声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.
init-method 和 destroy-method 方法的实现写在类里
## bean后置处理器
Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.
Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例.
类需要 implements BeanPostProcessor,重写postProcessBeforeInitialization 方法和 postProcessAfterInitialization 方法
加上bean后置处理器后,Spring IOC 容器对 Bean 的生命周期进行管理的过程:
* 通过构造器或工厂方法创建 Bean 实例
* 为 Bean 的属性设置值和对其他 Bean 的引用
* 将 Bean 实例传递给 Bean 后置处理器的 postProcessBeforeInitialization 方法
* 调用 Bean 的初始化方法init-method()
* 将 Bean 实例传递给 Bean 后置处理器的 postProcessAfterInitialization 方法
* Bean 可以使用了
* 当容器关闭时, 调用 Bean 的销毁方法destroy-method()
七、Bean配置——使用外部文件
有时需要在 Bean 的配置里混入==系统部署的细节信息(==例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离。
举例:连接jdbc
导入对应的c3p0.jar和mysql-connector包
建立一个信息文件
里面写入相关配置信息
引用外部文件
八、bean配置形式:基于XML文件&基于注解的配置方式
之前我们举例的都是基于XML文件配置的bean。
下面我们来讨论基于注解的配置方式。
基本使用
Spring有四种特定的注解(组件):
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称
xml中:声明<context:component-scan >
,base-package
属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.;当需要扫描多个包时, 可以使用逗号分隔。
如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,示例:
<context:include-filter>
子节点表示要包含的目标类
<context:exclude-filter>
子节点表示要排除在外的目标类
<context:component-scan>
下可以拥有若干个 <context:include-filter> 和 <context:exclude-filter>
子节点
举例:
需要导入Namespace“context” 以及 spring-aop-5.0.4.jar
包结构:
类:
@Component
@Controller
@Service
@Respository
xml中:
测试:
结果:
当类为组合关系的时候如何通过注解方法配置
该实例可以装配具有 @Autowired 和 @Resource 、@Inject注解的属性.建议使用Autowired。
@Autowired 注解自动装配具有兼容类型的单个 Bean属性(类里面有另外一个类)
* 构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
举例:
controller里面有service
service里面有respository
测试及结果
- 默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false
举例:
component无注解的时候,但respository里面包括了component类,spring会找不到匹配的bean而抛异常
respository
component
解决:设置 @Authwired 注解的 required 属性为 false
测试及结果:
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时(就是有多个类实现了同一个类,Spring匹配到两个,不知道该用哪个类进行bean的实现——通过类型的自动装配将无法工作) 。
一种方法是:在注解()里边写上对应的名字
另一种方法是:在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
举例:
注意到service里面的userRespository名字与@Respository()里边要一致,spring才能够匹配。
使用@Qualifier注解:写上要指定的具体的类
方法中参数也可以使用Qualifier注解
- @Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配.
- @Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean.
- @Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值