前言

欢迎来到本篇文章,鸽了好久了,今日继续写下 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 标签有 idclass 特色。

这个 id 是每个 Bean 都有的一个标识符(identifier),这些标识符在 Spring IoC 容器中有必要是仅有的

一个 Bean 一般只有一个标识符。假如它需求一个以上的标识符,那么多余的标识符能够被视为别号

在依据 XML 的装备元数据中,我们能够运用 id 特色、name 特色或两者来指定 Bean 的标识符。

命名习惯

习惯上,这儿关于 Bean 界说的命名和关于我们命名 Java 类中的特色名是一样的,便是驼峰命名,小写字母开头。比方 userServiceuserDaologinController 等等。

还有,假如想起多个别号,那么用 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 种办法分别是:

  1. 经过结构办法实例化
  2. 经过静态工厂办法实例化
  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 之间的相互依靠。

最终的最终

期望各位屏幕前的靓仔靓女们给个三连!你轻轻地点了个赞,那将在我的心里国际增添一颗亮堂而耀眼的星!

我们下期再见!