前言程序员
使用 Java 做为第一开发语言的朋友们,相信你们或多或少的都使用过 Spring 这个开发框架,能够说 Spring 框架真是咱们 Java 程序员的春天,在 Spring 中 Bean 是其中最重要的概念之一,是学习其它高级知识的基础,Bean 说白了其实就是一个被 Spring 框架管理的对象,今天咱们来看看 Bean 在 Spring 中是如何被造出来的。框架
Bean 要如何定义ide
假如你有以下这样的一个 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 对象呢?学习
无非就是须要以下这些信息:ui
2.1设计
类名code
首先类名确定是须要的,这样到时候才能经过类名加载到这个类。对象
2.2blog
实例别名
当咱们在一个容器中若是一个类有多个实例或者不想经过一个类名来描述一个实例时,这时经过设置一个别名就能够很方便的描述该实例了。
2.3
构造函数
咱们知道 Java 中建立一个类的实例首先就会调用该类的构造函数,当有多个构造函数时,须要明确的描述要使用哪一个构造函数来建立对象,好比经过传入不一样的参数类型来选择不一样的构造函数。
2.4
类的属性设置
当咱们没有在构造函数中传入属性,好比上面的 Programmer 能够直接经过无参构造函数就能够建立出来了,后面若是须要设置实例的属性则须要调用其设置属性的方式来进行设置,因此属性方法也是必要的。
2.5
初始化方法
有时候咱们须要在一个实例化完成以后作一些咱们自定义的业务逻辑,好比想让上面例子中的 Programmer 在实例化完成以后就显示我的资料(调用 showMaterial() 方法),这种场景使用初始化方法就很合适了。
2.6
销毁方法
说到销毁,你们可能都会想到和资源有关,好比一个共识就是你们通常都把资源释放类的工做放在 finally 代码块中确保资源能够获得释放,一样当一个 Bean 以后链接使用了某些资源时,当销毁后想要对这些资源进行释放,这时候就能够经过其 销毁方法 来释放资源。
2.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,这个方法其实是调用了抽象实现类 AbstractRefreshableApplicationContext 的 refreshBeanFactory 方法,该方法首先会先判断此时是否还有 beanFactory ,若是有的话会先销毁 beanFactory,而后再从新建立一个 BeanFactory(其实是 DefaultListableBeanFactory 类型),最后会调用 loadBeanDefinitions 加载咱们定义的 XMl 配置,方法使用的是 XmlBeanDefinitionReader 来读取的 XMl 配置,下面一块儿来深刻的了解一下 Spring 生成 Bean 的过程。
建立 Bean 的过程
首先咱们看看 BeanFactory 类图,以下所示:
Bean 的总体建立流程以下所示:
总结
本文简要的讲述了 Spring 建立 Bean 的主要流程,还有许多细节的地方须要深刻研读源码才能了解,在这里先给本身一个小目标,后续会本身实现一个简易版本的 Spring(IOC、AOP),预知后事如何,请听下回分解。。。