这里写目录标题
最近在学习Spring源码这一块,看到了Spring中的FactoryBean
部分,做个笔记加深一下印象和理解。
本章主要将一下beanName
和&beanName
获取到的是啥,以及从哪些容器获取对象。
简介
说道FactoryBean
肯定会和BeanFactory
结合起来。其实也有点见名思意。
FactoryBean
: 工厂Bean,这是一个用来创建对象的Bean工厂
BeanFactory
: Bean工厂,这玩意啥都有,是一个大的工厂对象。
看源码对BeanFactory
的解析:
BeanFactory 生产的对象 由 Spring来控制整个生命周期
再看FactoryBean
:
可以由我们自己去管理
要创建的Bean对象。
结果演示
环境
XML文件
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="studentFactory" class="entity.StudentFactory">
</bean>
</beans>
实体类和实体类工厂
// 实现FactoryBean的类
public class StudentFactory implements FactoryBean<Student> {
public Student getObject() throws Exception {
return new Student();
}
public Class<?> getObjectType() {
return Student.class;
}
}
// 实体类
public class Student {
}
Main类
public class FactorybeanTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
StudentFactory factoryBean = (StudentFactory) context.getBean("&studentFactory");
System.out.println(factoryBean);
Student studentBean = (Student) context.getBean("studentFactory");
System.out.println(studentBean);
}
}
结果
结论
如果想通过beanName
取出FactoryBean
对象,必须在beanName
前加&
符号,否则取出来的是FactoryBean工厂生成的对象
源码分析
1、转变BeanName
通过doGetBean
方法进去到容器中去找对应的Bean,会对传入的name进行处理从而得到BeanName
2、从容器中获取BeanName对应的对象
注意,这里是通过BeanName去获取对象,我们在beans.xml
文件中已经配置了StudentFactory
这个类,所以这个类肯定是在容器中的,那么肯定能从容器中获取到这个FactoryBean工厂对象。
3、核心方法getObjectForBeanInstance
既然能获取到FactoyBean
对象信息,所以会接着往下走,从Bean实例中获取对象。
最终进入到父类(org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance)的处理方法。
4、判断逻辑
1、先判断name
是否为空,是否是&
开头
如果是name
以&
开头,则进行一些校验后直接返回去了。
判断的依据通过name
是否以&
开头
2、 接下来继续走逻辑,通过BeanName从某个
缓存中获取对象
这个缓存就是factoryBeanObjectCache
,先记住后面要用。
3、如果缓存取不到就进行创建对象处理
4、创建对象过程
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
真正开始创建Bean对象。
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
5、加入到Bean对象factoryBeanObjectCache
容器中
判断Bean容器中是否有对应的FactoryBean,有的话。将该FactoryBean刚才创建的Bean对象加入到factoryBeanObjectCache
容器中
小结
简易流程图简单小结一下
- 解析name得到beanName
- 通过name判断要获取的对象
- 通过beanName从另一个缓存中获取对象。
DEBUG查看容器对象信息
factoryBeanObjectCache容器
BeanDefintionMap容器
一级缓存 singletonObjects 中
从而我们得知:beanName
都是唯一的,在Spring中的一级缓存和BeanDefintionMap中都是存FactoryBean
这个工厂类,而另一个缓存容器factoryBeanObjectCache
则存放该工厂所生产的对象信息。