Spring(一)——Bean配置

一、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
    内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里, 不需要设置任何 id 或 name 属性
    内部Bean

级联属性:
在 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
Component
@Controller
Controller
@Service
Service
@Respository
这里写图片描述
这里写图片描述

xml中:
这里写图片描述
测试:
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 的名称作为键值

猜你喜欢

转载自blog.csdn.net/github_38687585/article/details/79831816