Spring-IoC 基于xml管理

现大多使用注解方式,xml方式并不简洁,本文仅记录xml用作基础学习。

0、前提

首先在父项目的pom.xml中配置好依赖们。然后子模块也可以使用这些依赖。
  • 在resource目录下创建Spring的xml文件,名称无要求,本文使用bean.xml。文件最上头的几行为约束,表示可以用哪些标签等,如要使用其他标签,需先在此处添加对应的三行(xmlns:标签名=".../标签名"、xsi:schemaLocation="... ...",都把链接的末尾改为标签名)
  • 在bean.xml文件中写bean标签:id为类的唯一标识,class为类的全类名(包名+类名)
  • 根据bean.xml文件创建IoC容器

一、获取Bean:

有三种方式获取bean,基于id、基于class、基于id和class一起使用。

1. 根据id获取:getBean("id")

2. 根据类型获取:getBean(类名.class)

注意事项:
当根据类型获取bean时,要求IoC容器中指定类型的bean有且只能有一个。
当IOC容器中一共配置了多个,根据类型获取时会抛出异常。
期望匹配单实例的bean,但发现了两个,IoC不知道找谁:
只能使用其他两种方式。
扩展:

接口不能new,只能new接口的实现类。

使用实现类的类型可以获取到bean,所以此处试验接口类型能不能获取bean。

如果组件类实现了接口,根据接口类型可以获取 bean 吗?
可以,前提是bean唯一
接口UserDao,实现类UserDaoImpl。
如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型可以获取 bean 吗?
不行,因为bean不唯一
接口UserDao,实现类UserDaoImpl、PersonDaoImpl。
原因与注意事项类似,不知道找谁。
结论:

根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:[对象 instanceof指定的类型」的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。

java中,instanceof运算符用于判断前面的对象是否是后面的类,或其子类、实现类的实例。如果是返回true,否则返回false。也就是说:用instanceof关键字做判断时,instanceof操作符的左右操作必须有继承或实现关系

3. 根据id和类型获取:getBean("id", 类名.class)


二、依赖注入

依赖注入是指在创建对象时,给属性设置值。

原始写法:通过set方法和有参构造器赋值

有两种实现方式:Setter和构造器。

1. 基于Setter注入:<property>

  • 首先创建类,定义属性和set方法。

在类前使用lombok的@Data注解可以不用手动get、set、toString等。

  • 在bean.xml配置文件中写bean标签,使用<property>标签调用set方法赋值。

name为属性,value为具体赋值。

2. 基于构造器注入:<constructor-arg>

  • 首先创建类,定义属性和有参构造方法。
  • 在bean.xml配置文件中写bean标签,使用<constructor-arg>标签调用有参构造方法赋值。

name为属性,value为具体赋值。(name也可以用index索引但不推荐,因为顺序要一致)


3. 特殊值处理

3.1 字面量

字面量没有引申含义,就是我们看到的这个数据本身。

使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量

3.2 null-空值

不能写成如下形式,此时为name属性赋值null字符串

3.3 xml实体:转义

&lt;

3.4 CDATA节:<![CDATA[...]]>

4. 特殊类型属性注入

4.1 对象类型属性

一个类对象中有属性是另一个对象,例如在员工对象中有一个部门对象。

有三种方式:

4.1.1 引用外部bean------ref

在bean.xml中写好两个类的bean,部门bean和员工bean。

在员工bean的部门属性中用ref代替value赋值,ref="部门bean的id"

4.1.2 内部bean

在bean.xml中写员工bean,在员工bean的部门属性中声明部门bean。

4.1.3 级联属性赋值

在引用外部bean的基础上,使用对象.属性可以改变值。

4.2 数组类型属性------<array>标签

员工有多个爱好,用数组表示。

4.3 集合类型属性

4.3.1 List集合------<List>标签

一个部门有多个员工,部门对象bean中有一个员工类型的List。

因为员工是对象类型所以用ref引用外部bean,如果是字符串或其他,用value。

4.3.2 Map集合------<map><entry><key><value><ref>标签

也可以用map-key/value,一个学生有多个老师

4.3.3 引用集合类型的bean------<util:list><util:map>

由于要使用util标签,要先在bean.xml文件的最上头引入util,否则不能用:

一个学生有多门课-List,多个老师-Map,课和老师为对象类型。

两个lesson对象bean:

两个teacher对象bean:

student的bean:ref为对应util的id

4.4 p命名空间

要使用p标签,在bean.xml文件最上添加:

使用p命名空间,可以用:p:属性="值"进行赋值,而不用name、value了。

5. 引入外部属性文件

由于bean.xml文件中有很多bean,不利于修改和维护,所以把一些特定的值放在外部文件中,在引入外部文件进行注入。修改时只需修改外部文件,而不用修改配置文件。

常见的如数据库。

5.1 首先在pom.xml文件中添加数据库驱动和数据源等相关依赖。
5.2 创建外部属性文件(resource目录下),一般是.properties后缀格式,定义数据库信息,此处为jdbc.properties

=左边为名字,右边为赋值

5.3 引入外部属性文件:先在bean.xml最上头引用context名称空间,使用<context>标签引入外部属性文件,在bean中的value使用${}表达式完成注入

location为外部属性文件类路径:

class为德鲁伊连接池对象路径,value使用外部文件中的名字:

测试:


三、bean的作用域-scope

注意创建时机不同。

1. 单实例:

两个对象为同一个

2. 多实例:

两个对象不同


四、bean的生命周期

bean对象从创建到销毁的过程。

1. 生命周期过程:

bean对象创建(调用无参构造器)
给bean对象设置属性(set方法)
bean的后置处理器(初始化之前)
bean对象初始化(需在配置bean时指定初始化方法)
bean的后置处理器(初始化之后)
bean对象就绪可以使用
bean对象销毁(需在配置bean时指定销毁方法)
IOC容器关闭

2. 后置处理器:

实现BeanPostProcessor接口,并重写两个方法:postProcessBeforeInitialization和postProcessAfterInitialization。
还需在IoC容器中配置后置处理器,需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IoC容器中所有bean都会执行

class为接口实现类的全类名:

3. 测试

输出:


五、FactoryBean

FactoryBean是Spring的一种常用机制。帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来。和普通的bean不同,配置一个FactorvBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值决定创建什么对象。

将来整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的。

使用:

实现FactoryBean接口的类,重写getObject()方法,返回一个对象。

配置文件:

getBean("user")返回的user对象,而不是class的MyFactoryBean对象。

六、基于xml的自动装配

不使用自动装配即上述中的二、4.1部分使用ref。

在IoC容器匹配bean时,自动为该bean依赖的类类型、接口类型的属性赋值。

有两种方式:byName和byType

创建三个包,controller、Service、dao,其中controller包下有一个UserController类,Service包下有userService接口和实现该接口的userServiceImpl类,dao包下有userDao接口和实现该接口的userDaoImpl类。

1. 在bean.xml中的bean标签内使用autowired ="byType",在IoC容器中根据类型找bean自动装配。最好保证bean唯一。
如果没有找到匹配的类型,则该属性不匹配,默认赋值为null。如果找到多个,抛出异常NoUniqeBeanDefinitionException。
2. autowired ="byName",需保证id标识与类定义中的属性名称一致

不一致则报错,会赋空值。

参考:b站尚硅谷

相关推荐
冷琴19964 分钟前
基于java+springboot的酒店预定网站、酒店客房管理系统
java·开发语言·spring boot
daiyang123...30 分钟前
IT 行业的就业情况
java
Nightselfhurt42 分钟前
Spring cloud 中gateway原理
spring·spring cloud·gateway
爬山算法1 小时前
Maven(6)如何使用Maven进行项目构建?
java·maven
.生产的驴1 小时前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
爱学的小涛1 小时前
【NIO基础】基于 NIO 中的组件实现对文件的操作(文件编程),FileChannel 详解
java·开发语言·笔记·后端·nio
吹老师个人app编程教学1 小时前
详解Java中的BIO、NIO、AIO
java·开发语言·nio
爱学的小涛1 小时前
【NIO基础】NIO(非阻塞 I/O)和 IO(传统 I/O)的区别,以及 NIO 的三大组件详解
java·开发语言·笔记·后端·nio
北极无雪1 小时前
Spring源码学习:SpringMVC(4)DispatcherServlet请求入口分析
java·开发语言·后端·学习·spring
琴智冰1 小时前
SpringBoot
java·数据库·spring boot