关于java:Spring-是如何造出一个-Bean-的

6次阅读

共计 2770 个字符,预计需要花费 7 分钟才能阅读完成。

前言

应用 Java 作为第一开发语言的敌人们,置信大家或多或少的都应用过 Spring 这个开发框架,能够说 Spring 框架真是咱们 Java 程序员的春天,在 SpringBean 是其中最重要的概念之一,是学习其它高级常识的根底,Bean 说白了其实就是一个被 Spring 框架治理的对象,明天咱们来看看 BeanSpring 中是如何被造出来的。

1. Bean 要如何定义

如果你有如下这样的一个 Programmer 类,这个程序员类有三个属性:姓名 (name) 年龄 (age) 是否有女朋友(hasGirlFriend)(P.S. 失常状况下 hasGirlFriend 属性应该都是 false),还有一个显示个人资料的办法 showMaterial

/**
 * @Author: mghio
 * @Date: 2020-10-05
 * @Description: Programmer.
 */
public class Programmer {

    private String name;

    private Integer age;

    private Boolean hasGirlFriend;

    public void showMaterial() {System.out.println("name:" + name + ", age:" + age + ", hasGirlFriend:" + hasGirlFriend);
    }
}

当初请你思考一下,如果让你来设计该如何在一个 Spring 容器中形容这样的一个 Programmer 对象呢?

无非就是须要如下这些信息:

1.1 类名

首先类名必定是须要的,这样到时候能力通过类名加载到这个类。

1.2 实例别名

当咱们在一个容器中如果一个类有多个实例或者不想通过一个类名来形容一个实例时,这时通过设置一个别名就能够很不便的形容该实例了。

1.3 构造函数

咱们晓得 Java 中创立一个类的实例首先就会调用该类的构造函数,当有多个构造函数时,须要明确的形容要应用哪个构造函数来创建对象,比方通过传入不同的参数类型来抉择不同的构造函数。

1.4 类的属性设置

当咱们没有在构造函数中传入属性,比方下面的 Programmer 能够间接通过无参构造函数就能够创立进去了,前面如果须要设置实例的属性则须要调用其设置属性的形式来进行设置,所以属性办法也是必要的。

1.5 初始化办法

有时候咱们须要在一个实例化实现之后做一些咱们自定义的业务逻辑,比方想让下面例子中的 Programmer 在实例化实现之后就显示个人资料(调用 showMaterial() 办法),这种场景应用初始化办法就很适合了。

1.6 销毁办法

说到销毁,大家可能都会想到和资源无关,比方一个共识就是大家个别都把资源开释类的工作放在 finally 代码块中确保资源能够失去开释,同样当一个 Bean 之后连贯应用了某些资源时,当销毁后想要对这些资源进行开释,这时候就能够通过其 销毁办法 来开释资源。

1.7 作用域

有些 Bean 可能须要在整个容器中只有一个,也就是 单例 ,而有些可能要求每一次申请对应的 Bean 都不一样,这时能够通过一个 作用域 的概念,来辨别不同要求的 Bean,当容器发现这个类是 单例 的,就会复用已存在的 Bean,否则才从新创立。

当然这里只是列举一些集体感觉比拟重要的属性,还有其它的一些属性须要减少。在 Spring 框架中 Bean 的定义是通过一个 BeanDefinition 类来形容的。

在没有应用 SpringBoot 之前咱们都是通过 XML 配置而后 Spring 来解析生成 Bean 的,同时咱们也能够通过代码形式应用 BeanDefinitionBuilder 生成 Bean,具体代码如下所示:

/**
 * @Author: mghio
 * @Date: 2020-10-05
 * @Description:
 */
public class ProgrammerTest {public static void main(String[] args) {new Programmer().showMaterial();

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Programmer.class);
        beanDefinitionBuilder.addPropertyValue("name", "mghio");
        beanDefinitionBuilder.addPropertyValue("age", 18);
        beanDefinitionBuilder.addPropertyValue("hasGirlFriend", false);

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerBeanDefinition("programmer", beanDefinitionBuilder.getBeanDefinition());

        Programmer programmer = (Programmer) beanFactory.getBean("programmer");
        programmer.showMaterial();}

}

运行后果如下:

在应用 XML 形式时个别是通过调用 ClassPathXmlApplicationContext 来注册 Bean 的,其构造函数能够传入具体的 XMl配置文件的门路,能够是一个或者多个,甚至还能够是通配符。在构造函数外部就会调用相熟的 refresh 办法了。

深刻 refresh 办法能够发现,在该办法中调用了 obtainFreshBeanFactory 办法来获取生成的 Bean,这个办法实际上是调用了形象实现类 AbstractRefreshableApplicationContextrefreshBeanFactory 办法,该办法首先会先判断此时是否还有 beanFactory,如果有的话会先销毁 beanFactory,而后再从新创立一个 BeanFactory(实际上是 DefaultListableBeanFactory 类型),最初会调用 loadBeanDefinitions 加载咱们定义的 XMl 配置,办法应用的是 XmlBeanDefinitionReader 来读取的 XMl 配置,上面一起来深刻的理解一下 Spring 生成 Bean 的过程。

2. 创立 Bean 的过程

首先咱们看看 BeanFactory 类图,如下所示:

Bean 的整体创立流程如下所示:

3. 总结

本文简要的讲述了 Spring 创立 Bean 的次要流程,还有许多细节的中央须要深刻研读源码能力理解,在这里先给本人一个小指标,后续会本人实现一个繁难版本的 SpringIOCAOP),预知后事如何,请看下篇博文。。。

正文完
 0