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 新特性:泛型依赖注入
1、容器是spring的核心,使IoC管理所有和组件
2、spring的两种容器:a、BeanFactoy b、ApplicationContext
3、BeanFactory:BeanFactory使用延迟加载所有的Bean,为了从BeanhFactory得到一个Bean,只要调用getBean()方法,就能获得Bean
4、ApplicationContext:
5、ApplicationContext的三个实现类:
a、ClassPathXmlApplication:把上下文文件当成类路径资源
b、FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息
c、XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息
几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory
ApplicationContext 在初始化上下文时就实例化所有单例的 Bean。
调用getBean()方法从容器中获取Bean对象
Spring 支持 3 种依赖注入的方式:属性注入、构造器注入、工厂方法注入(很少使用,不推荐)
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
属性注入使用
元素, 使用 name 属性指定 Bean 的属性名称,value 属性或
子节点指定属性值
属性注入是实际应用中最常用的注入方式
public class HelloWorld {
String name;
public void setName(String name) {
this.name = name;
}
}
<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;
}
字面值:
*
* 用字符串表示,基本数据类型、对象、封装类都可以用字面值注入
* 特殊字符 :用把字面值包裹起来
引用其他Bean:
* 通过 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用.
级联属性:
在 Spring中可以通过一组内置的 xml 标签(例如:
) 来配置集合属性.,
配置 java.util.List 类型的属性, 需要指定
标签
配置 java.util.Set 类型的属性, 需要使用
标签
Java.util.Map 通过 标签定义,
标签里可以使用多个
作为子标签. 每个条目包含一个键和一个值.
java.util.Properties使用
定义, 该标签使用多个
作为子标签. 每个
标签必须定义 key 属性
使用基本的集合标签定义集合时, 不能将集合作为独立的 Bean 定义, 导致其他 Bean 无法引用该集合, 所以无法在不同 Bean 之间共享集合.
可以使用 util schema 里的集合标签定义独立的集合 Bean. 需要注意的是, 必须在
根元素里添加 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 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之.
Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean
子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置,子 Bean 也可以覆盖从父 Bean 继承过来的配置。
父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置
的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean。
并不是
元素里的所有属性都会被继承. 比如: autowire, abstract 等。
.
也可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true。
Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好
如果前置依赖于多个 Bean,则可以通过逗号,空格或的方式配置 Bean 的名称
在 Spring 中, 可以在
元素的 scope
属性里设置 Bean 的作用域.
是==单例模式==,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例;
注意这里的Spring singleton模式是默认缺省的==饿汉模式== 启容器时(即实例化容器时),为所有spring配置文件中定义的bean都生成一个实例。
可是这样做会导致系统的开销比较大,为了不占用过大的资源或者是减少开销,一般我会在spring中添加缺省文件:
<beans default-lazy-init="true">
将系统默认的饿汉模式转换成懒汉模式,也就是在第一次请求的时候我们才生成一个实例。
原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。
prototype作用域Bean的创建、销毁代价比较大。
用在web
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 配置相分离。
举例:连接jdbc
导入对应的c3p0.jar和mysql-connector包
里面写入相关配置信息
之前我们举例的都是基于XML文件配置的bean。
下面我们来讨论基于注解的配置方式。
Spring有四种特定的注解(组件):
@Component: 基本注解, 标识了一个受 Spring 管理的组件
@Respository: 标识持久层组件
@Service: 标识服务层(业务层)组件
@Controller: 标识表现层组件
对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称
xml中:声明
,base-package
属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.;当需要扫描多个包时, 可以使用逗号分隔。
如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,示例:
子节点表示要包含的目标类
子节点表示要排除在外的目标类
下可以拥有若干个
子节点
举例:
需要导入Namespace“context” 以及 spring-aop-5.0.4.jar
包结构:
类:
@Component
@Controller
@Service
@Respository
该实例可以装配具有 @Autowired 和 @Resource 、@Inject注解的属性.建议使用Autowired。
@Autowired 注解自动装配具有兼容类型的单个 Bean属性(类里面有另外一个类)
* 构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解
举例:
controller里面有service
service里面有respository
测试及结果
解决:设置 @Authwired 注解的 required 属性为 false
测试及结果:
默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时(就是有多个类实现了同一个类,Spring匹配到两个,不知道该用哪个类进行bean的实现——通过类型的自动装配将无法工作) 。
一种方法是:在注解()里边写上对应的名字
另一种方法是:在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称
注意到service里面的userRespository名字与@Respository()里边要一致,spring才能够匹配。
使用@Qualifier注解:写上要指定的具体的类
方法中参数也可以使用Qualifier注解