前言
在上一篇文章里我们已经详细的了解了BeanDefinition的创建和注册。那么接下来我们就应该学习spring是如何将BeanDefinition变成对象,并存储在spring容器中的了。但是这个转换过程先不着急学,咱们在此之前还需要先大概了解一下spring创建对象的整体流程。
在这一篇中我们将介绍spring创建对象的整体流程。在讲解流程之前我先将流程中的节点拆开讲解一下,最后再串联在一块。
Spring创建对象的方式
简单对象的创建
- 可以通过构造方法new的方式直接创建对象,底层是通过反射的方式创建。
复杂对象的创建
什么是复杂对象:不能通过直接new的方式直接创建的对象,这种对象的特征如下:
- 接口类型的对象
- 链接数据库的Connection对象,这个对象需要userName、password、driver驱动 等共同构建Connection对象,同理还有sqlSessionFactory对象也是。
复杂对象创建的方式:
- FactoryBean 的方式创建,而这种创建方式需要实现三个方法:
- getObject():书写创建复杂对象的代码,然后spring工厂会回调这个方法
- getObjectType():返回类型
- isSingleton:定义是否是单例
- 静态工厂 的方式创建,而这种创建方式需要如下操作:
- 定义一个类
- 在类内部提供一个静态方法
- 在静态方法内部返回所要创建的对象
- 标签中class属性指向这个类, factory-method属性指向这个静态方法
- 实例工厂 的方式创建,而这种创建方式需要如下操作:
- 定义一个类
- 在类内部提供一个方法
- 在方法内部返回所要创建的对象
- 在xml中先定义一个此类的
- 在xml中再定义想要创建的,这个bean的factory-bean指向先定义的那个,这个bean的factory-method属性指向工厂bean所定义的那个方法。
注入的方式
在创建完对象之后,我们接下来要考虑的是如何为对象赋值。在spring中赋值也叫做注入,那么注入分为如下的方式:
- set注入:标签,这种注入是最常用的一种。spring底层用这种方式比较多。那么set注入又分为如下两种情况:
- 程序员来完成的注入:包括八种基本类型(int、byte、short、double),自定义的对象类型
- 容器(spring)的注入:这种类型的注入主要包括一堆Aware接口类型,其中包括 BeanNameAware接口,BeanFactoryAware接口等等,自定义类型的对象需要实现这些Aware接口,从而使得自定义类型对象获得这些Aware接口的各种能力。
需要注意的是,实现了这些Aware接口需重写接口的方法,而重写的方法也是set方法的一种,
问题:程序员自己定义的set先注入还是容器定义的set先注入呢?
答:程序员自己定义的set先注入。
- 构造:标签
- 自动:标签中的autowire属性,这个属性的选项有byName、byType,注解也是自动注入的另一种形式。
初始化的方式
- 实现 InitializingBean 接口 ,重写 afterPropertiesSet() 方法
public class User implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { //这里完成初始化逻辑。 } }
- 在对象类中定义一个方法,标签配置 init-method 属性,属性值指向那个在类中定义的方法。
public class User implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { //这里完成初始化逻辑。 } }
注意:如果开发者两种初始化方法都使用了,那么会优先执行第一种(也就是实现接口的那种),因为这是spring容器定义的。
销毁的方式
- 实现 DisposableBean 接口 ,重写 destroy() 方法
public class User implements DisposableBean { @Override public void destroy() throws Exception { //这里完成容器关闭后需要处理的后续操作 } }
- 在对象类中定义一个方法,标签配置 init-method 属性,属性值指向那个在类中定义的方法。
public class User { //销毁方法 public void destoryMethod() { //这里完成容器关闭后需要处理的后续操作 } } <bean id="user" class="com.thunisoft.project.spring.User" destroy-method="destoryMethod"/>
注意:如果开发者两种销毁方法都使用了,那么会优先执行第一种(也就是实现接口的那种),因为这是spring容器定义的。
加工对象
对象的加工是通过BeanPostProcessor来完成的,而对象的加工可以在两个时期进行加工:
- 属性注入之后
- 初始化bean之后
实现方式:
//第一步:定义一个类,实现BeanPostProcessor接口,重写此接口提供的两个方法
public class MyCustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//属性注入之后spring回调此方法
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//初始化bean之后spring回调此方法
return bean;
}
}
//第二步:将这个类注册成bean,交给spring管理。
<bean id="MyCustomBeanPostProcessor" class="com.thunisoft.project.spring.MyCustomBeanPostProcessor" />
Spring创建对象的流程
- 创建一个空对象,此时的对象还没有进行属性的填充。
- 对上一步的空对象里的属性进行填充。
- 将填充好属性的对象交给BeanPostProcessor进行初始化前的加工。
- 对加工后的对象进行初始化操作。
- 将经过初始化后的对象交给BeanPostProcessor进行初始化后的加工,得到最终对象。
- 调用者调用最终对象。
- 容器关闭时,进行销毁操作。
总结
本片文章讲解了Spring创建对象的流程,接下来会观看源码展开讲解Spring具体是怎么创建对象的。