Spring 中的 Bean
前言
欢迎来到本篇文章,鸽了好久了,今天继续写下 Spring 的内容:Spring 中 Bean 的基本概念、基本写法和 3 种实例化 Bean 的方式等。
什么是 Bean?
我们回顾下,什么是 Bean?这在上一篇文章 Spring 核心概念之一 IoC 中说过了,简而言之,一句话:被 Spring IoC 管理的对象,就是 Bean。
一个 Spring IoC 容器中管理着一个或多个 Bean,这些 Bean 是由我们提供给容器的配置元数据创建的(比如以 XML <bean />
形式定义的 Bean)。
「Bean Definition」的属性
在容器本身中,这些 Bean 定义被表示为 BeanDefinition
对象,它包含(除其他信息外)以下元数据(metadata)。
- 一个全路径类名:比如
cn.god23bin.demo.controller.DemoController
,这就是 Bean Definition 的实际实现类。 - Bean 的行为配置元素:它说明了 Bean 在容器中的行为方式(比如 scope、生命周期回调等等)。
- 对其他 Bean 的引用:这些被引用的 Bean 被称为协作者或依赖(collaborators or dependencies)。
- 其他配置的设置:比如,数据库连接池的大小限制或使用的连接数。
这些元数据对应着每个 Bean Definition 的一组属性。下表描述了这些属性:
属性 | 解释… |
---|---|
Class | 该属性是必需的,它指定了用于创建 bean 的 bean 类。 |
Name | 该属性唯一地指定 bean 标识符。 在基于 XML 的配置元数据中,我们可以使用 id 或 name 属性来指定 bean 标识符。 |
Scope | 该属性指定从特定 bean 定义创建的对象的范围,将在 bean 范围一章中讨论。 |
Constructor arguments | 这用于注入依赖关系,将在后续章节中讨论。 |
Properties | 这用于注入依赖关系,将在后续章节中讨论。 |
Autowiring mode | 这用于注入依赖关系,将在后续章节中讨论。 |
Lazy initialization mode | 懒加载模式,让 bean 告诉 IoC 容器在第一次被请求时创建一个 bean 实例,而不是在启动时。 |
Initialization method | 在容器设置了 bean 上的所有必要属性之后调用的回调。 它将在 bean 生命周期章节中讨论。 |
Destruction method | 当包含 bean 的容器被销毁时要使用的回调。 它将在 bean 生命周期章节中讨论。 |
Bean 的命名
以 XML 作为配置元数据的方式中,Bean 定义的基本格式是这样写的:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- 该 bean 的协作者和配置写在此处 -->
</bean>
<bean id="..." class="...">
<!-- 该 bean 的协作者和配置写在此处 -->
</bean>
<!-- 更多的 bean 定义写在此处 -->
</beans>
XML 中类似
<bean/>
由尖括号组成的写法,一般称为「标签」或者「元素」,在后面的说法中,可能有时出现标签的说法或者元素的说法,实际上都是指同一个东西,后续便不再说明
我们可以看到,bean 标签有 id
、class
属性。
这个 id
是每个 Bean 都有的一个标识符(identifier),这些标识符在 Spring IoC 容器中必须是唯一的。
一个 Bean 一般只有一个标识符。如果它需要一个以上的标识符,那么多余的标识符可以被视为别名。
在基于 XML 的配置元数据中,我们可以使用 id
属性、name
属性或两者来指定 Bean 的标识符。
命名习惯
习惯上,这里对于 Bean 定义的命名和对于我们命名 Java 类中的属性名是一样的,就是驼峰命名,小写字母开头。比如
userService
、userDao
、loginController
等等。还有,如果想起多个别名,那么用
name
属性指定别名是什么,比如name="别名1,别名2,别名3"
,多个别名之间可以用英文逗号、英文分号或者空格分隔。
Bean 的别名
除了使用 Bean 定义中的 name 属性来对 Bean 起别名,还可以使用 alias
标签给 Bean 起别名:
<bean id = "userService" name="userServiceName" ... ></bean>
<alias name="userServiceName" alias="userServiceAliasName" />
这样,名为 userServiceName
的 Bean 也有了另一个名字:userServiceAliasName
。
Spring 实例化 Bean 的 3 种方式
Spring 可以通过 3 种方式来为我们创建 Bean 对象,创建的对象是根据我们定义的配置元数据来进行创建的。
这 3 种方式分别是:
- 通过构造方法实例化
- 通过静态工厂方法实例化
- 通过实例工厂方法实例化
在上面的 Bean 定义的属性中,我们也看到了,在 <bean />
中有一个 class
属性,就是用来指定要实例化的对象的类型的。一般情况下,这个 class
属性是必须写的,除非是通过实例工厂方法实例化的 Bean,那么它的 Bean 定义可以不需要 class
属性。
1. 通过构造方法实例化
以 XML 为配置元数据为例,在默认的情况下,我们定义的 Bean 都是以构造方法来实例化 Bean 对象的。
这些交给 Spring 管理的 Bean,不需要实现 Spring 的某某接口或者继承 Spring 的某某类,只需要有一个无参的构造方法,就可以了。
这里也是 Spring 低侵入的特点,我们的类根本不需要去实现 Spring 特定的接口或继承特定的类进而实现 IoC 的功能。
<bean id="fans" class="cn.god23bin.demo.domain.entity.Fans">
<property name="name" value="god23bin" />
</bean>
以上面这个例子来说,这样定义的 Bean 就是通过 cn.god23bin.demo.domain.entity.Fans
的构造方法实例化的:
package cn.god23bin.demo.domain.entity;
public class Fans {
private String name;
public Fans() {
System.out.println("粉丝无参构造方法被调用了!");
}
// 省略 getter 和 setter
}
从 Spring IoC 容器中获取被管理的 Fans 对象,这个过程,Spring 就会根据配置元数据去使用构造方法实例化 Fans 对象。
测试:
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Fans fans = applicationContext.getBean(Fans.class);
System.out.println("fans name: " + fans.getName());
输出:
粉丝无参构造方法被调用了!
fans name: god23bin
2. 通过静态工厂方法实例化
假设我们有一些对象是从静态工厂中获取对象的,有一个静态工厂类,类中定义了一个静态方法,该方法是创建对象的:
package cn.god23bin.demo.domain.entity.factory;
import cn.god23bin.demo.domain.entity.Fans;
public class FansStaticFactory {
// 返回 Fans 对象的静态方法
public static Fans createFansInstance() {
System.out.println("粉丝静态工厂!");
Fans fans = new Fans();
fans.setName("练习两年半 | 你干嘛哎哟~~");
return fans;
}
}
接着在配置元数据中定义 Bean,将通过调用工厂的静态方法来创建 Bean 对象,使用 class
属性指定包含了静态工厂方法的类,使用 factory-method
属性指定创建对象的静态方法:
<bean id="fans" class="cn.god23bin.demo.domain.entity.factory.FansStaticFactory" factory-method="createFansInstance" />
测试:
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Fans fans = applicationContext.getBean(Fans.class);
System.out.println("fans name: " + fans.getName());
输出:
粉丝静态工厂!
粉丝无参构造方法被调用了!
fans name: 练习两年半 | 你干嘛哎哟~~
3. 通过实例工厂方法实例化
实例工厂:
package cn.god23bin.demo.domain.entity.factory;
import cn.god23bin.demo.domain.entity.Fans;
public class FansFactory {
public FansFactory() {
}
public Fans createFansInstance() {
System.out.println("粉丝工厂");
Fans fans = new Fans();
fans.setName("练习两年半 | 你干嘛哎哟~~ | 记得关注我噢~");
return fans;
}
}
和静态工厂实例化 Bean 对象类似,我们这里用实例厂方法进行 Bean 的实例化,从 Spring IoC 容器中调用现有工厂 Bean 的非静态方法来创建一个新的 Bean。
这里需要注意 Fans 这个 Bean 的
class
属性是不需要的。
<!-- 配置实例工厂 Bean,该对象包含了创建 Fans 对象的名为 createFansInstance 的方法 -->
<bean id="fansFactory" class="cn.god23bin.demo.domain.entity.factory.FansFactory">
<!-- 工厂的其他需要的依赖对象就配置在这里 -->
</bean>
<!-- 这个 Bean 将通过实例工厂创建 -->
<bean id="fans" factory-bean="fansFactory" factory-method="createFansInstance" />
总结
以上,就是本文的所有内容,主要介绍了 Spring 中 Bean 的概念和 Bean 的定义属性。
Bean 由配置元数据创建,比如以XML形式定义的 Bean。Bean 在容器中由 BeanDefinition 对象表示,它包含类名、行为配置元素、对其他 Bean 的引用以及其他配置设置等元数据属性。
Bean 的命名方式一般就是驼峰命名的。在基于XML的配置元数据中,可以使用 id 属性或 name 属性来指定 Bean 的标识符,Bean 的别名可以使用 alias 标签进行定义。
最后,我们说了 Spring 实例化 Bean 的三种方式:通过构造方法实例化、通过静态工厂方法实例化和通过实例工厂方法实例化。
当然,Bean 的内容不止这些,本文是对 Bean 的初步介绍。下一篇我们将介绍 Bean 之间的依赖关系,通过依赖注入来实现 Bean 之间的相互依赖。
最后的最后
希望各位屏幕前的靓仔靓女们
给个三连!你轻轻地点了个赞,那将在我的心里世界增添一颗明亮而耀眼的星!
咱们下期再见!
Spring 中的 Bean的更多相关文章
- JSP访问Spring中的bean
JSP访问Spring中的bean <%@page import="com.sai.comment.po.TSdComment"%> <%@page import ...
- 传统javabean与spring中的bean的区别
javabean已经没人用了 springbean可以说是javabean的发展, 但已经完全不是一回事儿了 用处不同:传统javabean更多地作为值传递参数,而spring中的bean用处几乎无处 ...
- 1.2(Spring学习笔记)Spring中的Bean
一.<Bean>的属性及子元素 在1.1中我们对<Bean>有了初步的认识,了解了一些基本用法. 现在我们进一步理解<Bean>属性及子元素. 我们先来看下< ...
- spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入
<spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...
- 第2章 Spring中的Bean
2.1 Bean的配置 Bean本质是Java中的类.Spring可以被看做一个大型工厂,这个工厂的作用就是生产和管理Spring容器zho中的Bean.想在项目中使用这个工厂,就需要对Spring的 ...
- spring 中的 bean 是线程安全的吗?
spring 中的 bean 是线程安全的吗? Spring 不保证 bean 的线程安全. 默认 spring 容器中的 bean 是单例的.当单例中存在竞态条件,即有线程安全问题.如下面的例子 计 ...
- Spring 中的bean 是线程安全的吗?
结论: 不是线程安全的 Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体sco ...
- spring(四):spring中给bean的属性赋值
spring中给bean的属性赋值 xml文件properties标签设置 <bean id="student" class="com.enjoy.study.ca ...
- Spring中与bean有关的生命周期
前言 记得以前的时候,每次提起Spring中的bean相关的生命周期时,内心都无比的恐惧,因为好像有很多,自己又理不清楚,然后看网上的帖子,好像都是那么一套,什么beanFactory啊,aware接 ...
- 【Spring】Spring中的Bean - 5、Bean的装配方式(XML、注解(Annotation)、自动装配)
Bean的装配方式 简单记录-Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)-Spring中的Bean 文章目录 Bean的装配方式 基于XML的装配 基于注解 ...
随机推荐
- python-爬虫-css提取-写入csv-爬取猫眼电影榜单
猫眼有一个电影榜单top100,我们将他的榜单电影数据(电影名.主演.上映时间.豆瓣评分)抓下来保存到本地的excle中 本案例使用css方式提取页面数据,所以会用到以下库 import time i ...
- 月光宝盒(vivo流量录制回放平台)正式对外开源
作者:vivo 互联网服务器团队- Liu Yanjiang 月光宝盒是一个基于流量录制回放的自动化测试平台,通过录制回放取代编写脚本进行自动化回归,提升测试效率和覆盖率.因为其解决方案具有很强的通用 ...
- 系统建模之UML用例视图
<用例视图> 1 用例图的目标 who「参与者」:确定谁要使用系统 what「功能」:他们使用系统做什么? 2 用例图-四大主要组件 2.1 参与者 参与者:与应用程序或系统进行交互的用户 ...
- [Linux]常用命令之【which/whereis/whatis】
1 which shows the full path of (shell) commands. 显示(系统)命令所在目录 [root@test ~]# which ls alias ls='ls - ...
- 设计模式之[构建者模式(Builder)]-C#
说明:构建一个大对象时,可以分解成一个部分一个部分的构建,比如一台电脑由CUP.内存.主板.屏幕等,这些配件本身就是一个复杂的制造过程,一个一个构建后然后才组装成一台新的电脑. 步骤 1.定义要构建的 ...
- vue中父组件给子组件传值的方法
顺序............................................. -------------列表组件,注册组件.调用使用组件----------------- 1,子组件 ...
- 编程开发8大语言详解,为什么Java是我最推荐的?
一. 前言 很多没有接触过编程语言的同学,都会觉得编程开发特别高端和神奇,担心理解不了更担心学不会. 当然,也有人会认为,你既然是做编程的,那么你应该什么都会,什么软件的开发都能完成,这是平哥经常听到 ...
- 深度学习02-03(图像处理、OpenCV实验案例)
OpenCV实验案例 文章目录 OpenCV实验案例 一.OpenCV安装 1. OpenCV介绍 2. 安装 二.OpenCV基本操作 1. 图像读取与保存 1)读取.图像.保存图像 2. 图像色彩 ...
- Spring源码:bean的生命周期(一)
前言 本节将正式介绍Spring源码细节,将讲解Bean生命周期.请注意,虽然我们不希望过于繁琐地理解Spring源码,但也不要认为Spring源码很简单.在本节中,我们将主要讲解Spring 5.3 ...
- NC23054 华华开始学信息学
题目链接 题目 题目描述 因为上次在月月面前丢人了,所以华华决定开始学信息学.十分钟后,他就开始学树状数组了.这是一道树状数组的入门题: 给定一个长度为 \(N\) 的序列 \(A\) ,所有元素初值 ...