Java-30 深入浅出 Spring - IoC 基础 启动IoC 纯XML启动 Bean、DI注入

点一下关注吧!!!非常感谢!!持续更新!!!

大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

目前已经更新到了:

  • MyBatis(已更完)
  • Spring(正在更新...)

上节进度

上节我们完成了 启动 IoC 容器 的部分。下面我们续接上节的内容,继续后续的内容。

纯 XML 模式

采用 Spring IoC 和 纯 XML 模式改造之前的 IoC 和 AOP 的实现。

准备工作

我们移除之前 beans.xml 文件,新增:

  • applicationContext.xml

创建 Bean 三种方式

之前我们是通过 beans.xml 文件,配合 BeanFactory 来完成对 Bean 的初始化等配置,接下来,我们将使用 Spring 框架来进行配置。

我们在 applicationContext 中配置 bean 之后, 将 Bean 交给 Spring 进行管理。

使用无参构造

在默认情况下,它会通过反射调用无参构造函数来创建对象,如果类中没有无参构造函数,将构建失败。

xml 复制代码
<bean id="wzkTransferService" class="wzk.service.impl.WzkTransferServiceImpl"></bean>

对应的截图如下所示:

使用静态方法

在实际开发中,我们使用的对象有些时候并不是直接通过构造函数可以创建出来的,它可能在创建的过程中会有很多额外的操作,此时会提供一个创建对象的方法,恰好这个方法是 static 修饰的。

例如,我们 JDBC 的时候,会用到 java.sql.Connection 接口的实现类,如果是 MySQL 数据库,那么用就是 JDBC4Connection,但是我们不会写 JDBC4Connection connection = new JDBC4Connection(),我们要注册驱动,还要提供 URL 等信息。

在实际的开发过程中,尤其早期我们没有使用 Spring 框架来管理和创建对象,但是设计的过程中,使用了工厂模式进行解耦,那么当接入 Spring 之后,就可以采用这种方式了。

我们先放写法:

xml 复制代码
<bean id="transferService" class="wzk.factory.BeanFactory" factory-method="getTransferService"></bean>

比如说我们有一个单例模式的类,为了保证安全,做了很多操作,而且比如 getInstance() 方法是 static 的。此时用无参构造也是不可行的(private 构造方法),那么我们就需要一个 factory-method 来获取当中的对象。

使用实例化方法创建

此种方法和上面静态方法创建其实类似,区别是用于获取对象的方法不再是static 方式修饰了,而是类中的一个普通的方法,此方法比静态方法创建的几率要高一些。

在早期的项目中,工厂中的方法也可能是静态的,也可能是非静态的,当时非静态的方法的时候,可以采用下面的配置方式:

xml 复制代码
<bean id="beanFactory" class="wzk.factory.BeanFactory"></bean>
<bean id="transferService" factory-bean="beanFactory" factory-method="getTransferService"></bean>

Bean 的生命周期

作用范围改变

在 Spring 框架管理 Bean 对象的创建时,Bean 对象默认都是单例的,但是它支持配置方式改变作用范围,作用范围官方提供的说明如下图:

在上图中提供的这些选项中,我们实际开发中用的最多的就是 Singleton(单例模式)和 prototype(原型模式,也叫多例模式)。

xml 复制代码
<!--配置service对象-->
<bean id="wzkTransferService"
class="wzk.service.impl.WzkTransferServiceImpl" scope="singleton"></bean>

不同作用范围的生命周期

单例模式:singleton

  • 对象初始化:创建容器时,对象就被创建了
  • 对象生存:只要容器存在,对象一直活着
  • 对象死亡:当容器销毁时,对象就被销毁了
  • 一句话总结:单例模式的 bean 对象生命周期与容器相同

多例模式:prototype

  • 对象初始化:当使用对象的时候,创建新的对象实例
  • 对象生存:只要对象在使用中,就一直活着
  • 对象死亡:当对象长时间不用时,被 Java 的垃圾回收器回收了
  • 一句话总结:多例模式 bean 对象,Spring 框架只负责创建,不负责销毁

Bean 标签属性

在基于 XML 的 IoC 配置中,Bean 标签是基础的标签,它表示了 IoC

容器中的一个对象,换句话说,如果一个对象让 Spring 管理,在 XML 的配置中都需要使用此标签配置,Bean 标签的属性如下:

  • id 属性:用于给 bean 提供一个唯一标识,在一个标签内部,标识必须唯一。
  • class 属性:用于指定创建 Bean 对象的全限定类名
  • name 属性:用于给 Bean 提供一个或者多个名称,多个名称和空格分隔
  • factory-bean 属性:用于指定创建当前 Bean 对象的工厂 Bean 的唯一标识,当指定了此属性之后,class 属性失效
  • factory-method 属性:用于指定创建当前 bean 对象的工厂方法,如配置 factory-bean 属性使用,则 class 属性失效,如配合 class 属性使用,则方法必须是 static 的。
  • scope 属性:用于指定 bean 对象的作用范围,通常情况下就是 singleton,当用到多例模式的时候,可以配置 prototype。
  • init-method 属性:用于指定 bean 对象的初始化方法,此方法会在 bean 对象装配后调用,必须是一个无参方法。
  • destory-method 属性:用于指定 bean 对象的销毁方法,此方法 bean 对象销毁前执行,它只能为 scope 是 singleton 时起作用。

DI注入的XML配置

按照注入的方式分类

  • 构造函数注入:顾名思义,就是利用带参构造函数实现对类成员的数据赋值
  • set 方式注入:它是通过类成员的 set 方法实现数据的注入(使用最多的)

按照注入的数据类型分类

  • 基本类型和 String:注入的数据类型是基本类型或者字符串类型的数据
  • 其他 Bean 类型:注入的数据类型如果是对象类型的,称为其他 Bean 的原因是,这个对象要求出现在 IoC 容器中,那么对于当前 Bean 来说,就是其他的 Bean 了
  • 复杂类型(集合类型):注入的数据类型是 Array,List,Set,Map,Properties 中的一种类型。

构造函数注入

构造函数注入,顾名思义,就是利用构造函数实现对类成员的赋值,它的使用要求是,类中提供的构造函数参数个数必须和配置的参数个数一致,且数据类型匹配。

同时需要注意的是,当没有参数构造时,则必须提供构造函数的注入,否则 Spring 框架会报错。

(代码用之前的)

我们这里可以看看例子,首先我的 WzkTransferServiceImpl 中依赖了 wzkAccountDao,但是我们的代码中,只提供了 set 的方法,而没有提供构造方法。

具体代码在这里:

java 复制代码
private WzkAccountDao wzkAccountDao;

public void setWzkAccountDao(WzkAccountDao wzkAccountDao) {
	this.wzkAccountDao = wzkAccountDao;
	System.out.println("set setWzkAccountDao: " + wzkAccountDao);
}

对应的截图如下所示:

而此时,我们在 applicationContext.xml 中,配置了构造器的注入方式:

xml 复制代码
<!-- 配置 Bean -->
    <bean id="wzkTransferService" class="wzk.service.impl.WzkTransferServiceImpl">
        <constructor-arg name="wzkAccountDao" ref="wzkAccountDao"></constructor-arg>
    </bean>

我们可以看到已经提示了,没有构造器的话 Spring 是会报错的:

在使用构造函数注入时,涉及的标签时 construct-arg,该标签有 如下的属性:

  • name:用于构造函数中指定名称的参数赋值
  • index:用于给构造函数中指定索引位置的参数赋值
  • value:用于指定基于类型或者 String 类型的数据
  • ref:用于指定其他 Bean 类型的数据,写的是其他 Bean 的唯一标识

Set 方法注入

利用提供的 setXxxx 方法来通过赋值的方式实现注入。

编写的 XML 如下:

xml 复制代码
<bean id="wzkAccountDao" class="wzk.dao.WzkAccountDao"></bean>
    <!-- 配置 Bean -->
    <bean id="wzkTransferService" class="wzk.service.impl.WzkTransferServiceImpl">
        <!-- 构造器注入 -->
        <!-- <constructor-arg name="wzkAccountDao" ref="wzkAccountDao"></constructor-arg> -->

        <!-- set方法注入 -->
        <!-- ref 引入对象 -->
        <property name="wzkAccountDao" ref="wzkAccountDao"></property>
        <!-- value 是插入值 -->
        <property name="name" value="wzkicu"></property>
    </bean>

对应的截图如下所示,同样的,如果属性不存在的话,会报错:

在使用 set 方法注入时,需要使用 property 标签,该标签属性如下:

  • name:指定注入时调用的 set 方法名称
  • value:指定注入的数据,它支持基本类型和 String 类型
  • ref:指定注入的数据,它支持其他 bean 类型,写的是其他 bean 的唯一标识

在复杂数据类型注入的时候,指的是集合类型的数据,集合分为两类:

  • List 结构
  • Map 结构

接下来就是注入的方式的选择,只能在构造函数和 set 方法中选择,我们的示例选用 set 方法注入。

在 List 结构的集合数据注入时,array、list、set 这三个标签通用,另外注值value 标签内部可以直接写值,也可以使用 bean 标签配置一个对象,或者用 ref 标签应用一个已经配合的 bean 的唯一标识。

在 Map 结构的集合数据注入时,map 标签使用 entry 子标签实现数据注入,entry 标签可以使用 key value 属性指定存入 map 中的数据。使用 value-ref 属性指定已经配置好的 bean 的引用。

同事 entry 标签中也可以使用 ref 标签,但是不能使用 bean 标签,而 property标签中不能使用 ref 或者 bean 标签引用对象。

相关推荐
橙序员小站2 小时前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
怒放吧德德2 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
雨中飘荡的记忆3 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
开心就好20254 小时前
UniApp开发应用多平台上架全流程:H5小程序iOS和Android
后端·ios
悟空码字5 小时前
告别“屎山代码”:AI 代码整洁器让老项目重获新生
后端·aigc·ai编程
小码哥_常5 小时前
大厂不宠@Transactional,背后藏着啥秘密?
后端
奋斗小强5 小时前
内存危机突围战:从原理辨析到线上实战,彻底搞懂 OOM 与内存泄漏
后端
小码哥_常5 小时前
Spring Boot接口防抖秘籍:告别“手抖”,守护数据一致性
后端
心之语歌6 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
None3216 小时前
【NestJs】基于Redlock装饰器分布式锁设计与实现
后端·node.js