https://zhuanlan.zhihu.com/p/97005407

https://blog.csdn.net/qq_35634181/article/details/104507465

总结

  1. FactoryBean的对象会先在createWebServer时,创建BeanWrapper,并放到factoryBeanInstanceCache缓存中
  2. 在预实例化时,走FactoryBean逻辑,调用getBean去执行属性注入、初始化过程(此时对象实例化直接从factoryBeanInstanceCache缓存中取)
  3. 完成FactoryBean的实现类初始化
  4. 调用实现类的getObject方法,从而对工厂中类进行功能增强

FactoryBean(实现类)的初始化

初始化入口依然是AbstractApplicationContext#finishBeanFactoryInitialization() ,走到DefaultListableBeanFactory类preInstantiateSingletons方法时,和普通bean逻辑不同,执行以下代码:

@Override
public void preInstantiateSingletons() throws BeansException { // Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//FactoryBean的初始化执行入口
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
//普通bean的执行入口
getBean(beanName);
}
}
}
}

调用Object bean = getBean(FACTORY_BEAN_PREFIX + beanName),后面基本和普通bean的初始化一致

其中不同有:instanceWrapper不为null,是createWebServer时放入factoryBeanInstanceCache中的

if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}

将FactoryBean实现类放入缓存调用链为:

SpringApplication#run() --> SpringApplication#refreshContext() --> SpringApplication#refresh() -->ServletWebServerApplicationContext#refresh() --> AbstractApplicationContext#refresh() --> AbstractApplicationContext#onRefresh() --> ServletWebServerApplicationContext#createWebServer() --> ServletWebServerApplicationContext#getWebServerFactory() --> DefaultListableBeanFactory#getBeanNamesForType() --> DefaultListableBeanFactory#doGetBeanNamesForType() --> AbstractBeanFactory#isTypeMatch() --> AbstractAutowireCapableBeanFactory#getTypeForFactoryBean() --> AbstractAutowireCapableBeanFactory#getSingletonFactoryBeanForTypeCheck()

mbd为:

// Generics potentially only match on the target class, not on the proxy...
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

bw为:

Object instance;
try {
// Mark this bean as currently in creation, even if just partially.
beforeSingletonCreation(beanName);
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
instance = resolveBeforeInstantiation(beanName, mbd);
if (instance == null) {
bw = createBeanInstance(beanName, mbd, null);
instance = bw.getWrappedInstance();
}
}
catch (BeanCreationException ex) {
......
}
finally {
// Finished partial creation of this bean.
afterSingletonCreation(beanName);
}

FactoryBean为:

FactoryBean<?> fb = getFactoryBean(beanName, instance);
if (bw != null) {
this.factoryBeanInstanceCache.put(beanName, bw);
}

获取FactoryBean实现类(非工厂)的过程

如(此时beanName前面没有&):

Object factoryBeanTest = context.getBean("factoryBeanTest");

会先在AbstractBeanFactory#doGetBean()中执行:

protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException { // Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
......
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
}

执行getObjectForBeanInstance方法:

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { ...... Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

调用getObjectFromFactoryBean,再调用doGetObjectFromFactoryBean方法:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
//object为null
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName); ......
}
}
}
}

最后调用实际FactoryBean实现类的getObject方法,完成工厂类的自定义功能增强

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
......
}
else {
//去执行实际实现类的getObject方法
object = factory.getObject();
}
} return object;
}

通过FactoryBean.getObject方式

如:

FactoryBean bean = (FactoryBean)context.getBean("&factoryBeanTest");
CustomTask customTask = (CustomTask)bean.getObject();

会通过AbstractBeanFactory#doGetBean()直接返回bean

protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException { // Eagerly check singleton cache for manually registered singletons.
//此时一级缓存singletonObjects中有数据
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
......
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

调用getObjectForBeanInstance,返回beanInstance

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // Don't let calling code try to dereference the factory if the bean isn't a factory.
//此时为true
if (BeanFactoryUtils.isFactoryDereference(name)) {
......
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
}

其后便是调用FactoryBean实现类的getObject方法,完成工厂类的自定义功能增强

FactoryBean实现示例:

@Component
public class FactoryBeanTest implements FactoryBean {
@Override
public Object getObject() throws Exception {
//一些自定义功能
......
return new CustomTask();
} @Override
public Class<?> getObjectType() {
return CustomTask.class;
}
}

springboot中调用例子:

@RestController
public class TestController { @Autowired
private AnnotationConfigServletWebServerApplicationContext context; @RequestMapping("/test")
public String test() throws Exception { Object factoryBeanTest = context.getBean("factoryBeanTest");
System.out.println(factoryBeanTest.toString()); FactoryBean bean = (FactoryBean)context.getBean("&factoryBeanTest");
CustomTask customTask = (CustomTask)bean.getObject();
customTask.execute();
return bean.getObject().toString();
}
}

Spring源码之FactoryBean的实现的更多相关文章

  1. Spring源码学习

    Spring源码学习--ClassPathXmlApplicationContext(一) spring源码学习--FileSystemXmlApplicationContext(二) spring源 ...

  2. Spring源码学习之:FactoryBean的使用

    转载:http://book.51cto.com/art/201311/419081.htm ==========个人理解========================= FactoryBean和B ...

  3. 【Spring源码分析】原型Bean实例化过程、byName与byType及FactoryBean获取Bean源码实现

    原型Bean加载过程 之前的文章,分析了非懒加载的单例Bean整个加载过程,除了非懒加载的单例Bean之外,Spring中还有一种Bean就是原型(Prototype)的Bean,看一下定义方式: & ...

  4. spring源码分析系列 (8) FactoryBean工厂类机制

    更多文章点击--spring源码分析系列 1.FactoryBean设计目的以及使用 2.FactoryBean工厂类机制运行机制分析 1.FactoryBean设计目的以及使用 FactoryBea ...

  5. Spring源码分析(十二)FactoryBean的使用

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 一般情况下,Spring通过反射机制利用bean的class属性指定实现 ...

  6. 【spring源码系列】之【FactoryBean类型的接口】

    1.概述 目前我们知道,spring创建bean有多种方式,比如xml方式创建,比如@Component,@Service,@Controler,@Repository注解创建,比如@Autowire ...

  7. spring源码:学习线索(li)

    一.spring xml配置(不包括AOP,主要了解在初始化及实例化过程中spring配置文件中每项内容的具体实现过程,从根本上掌握spring) <bean>的名字 &,alia ...

  8. Spring源码分析——BeanFactory体系之抽象类、类分析(二)

    上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之 ...

  9. spring源码分析(一)IoC、DI

    创建日期:2016.08.06 修改日期:2016.08.07 - 2016.08.12 交流QQ:992591601 参考书籍:<spring源码深度解析>.<spring技术内幕 ...

随机推荐

  1. MeteoInfoLab脚本示例:inpolygon

    inpollygon函数是用来判断带坐标(x/y)的数据是否在某个或者一组多边形(Polygon)中,返回的结果中如果做多边形内则值为1,否则值为-1.下面一个例子演示了利用一个shape文件和inp ...

  2. Python-selenium:鼠标键盘事件

    鼠标事件 # 每个模拟事件后需加.perform() 才会执行 # context_click() 右击 # double_click() 双击 # drag_and_drop(source, tar ...

  3. Apollo基于K8S的部署以及接入

    Apollo镜像服务 基于开源Apollo服务进行相关服务镜像打包,实际将分发apollo-adminservice.apollo-configservice和apollo-portal 这三个镜像安 ...

  4. D - 活动选择

    Description 学校的大学生艺术中心周日将面向全校各个学院的学生社团开放,但活动中心同时只能供一个社团活动使用,并且每一个社团活动开始后都不能中断.现在各个社团都提交了他们使用该中心的活动计划 ...

  5. Pytest配置文件声明自定义用例标识

    使用pytest.ini添加自定义用例标识: [pytest] # 1.使用没有注册过的标记抛出错误 addopts = --strict-markers # 2.自定义标记 markers = sm ...

  6. git学习(五) git diff操作

    git diff操作 git diff用于比较差异: git diff 不加任何参数 用于比较当前工作区跟暂存区的差异 git diff --cached 或者--staged 对比暂存区(git a ...

  7. MySQL设置慢查询

    MySQL的慢查询日志是用来记录在MySQL中响应时间超过阀值的语句,则会被记录到慢查询日志中(运行时间超过long_query_time值的SQL语句):   慢查询相关参数: slow_query ...

  8. 学python,大概要多久?

    都让开!本人文科生,自学Python 2年半,作为一个曾经完全0基础,啥都不懂纯靠自学学会python的文科生,有一些不成熟的小建议可以分享一下. 首先不要觉着编程难,只要你认识26个英文字母,有一点 ...

  9. 想买保时捷的运维李先生学Java性能之 运行时数据区域

    前言 不知道自己不知道,不知道自己知道,知道自己不知道,知道自己知道,目前处于知道自己不知道这个阶段,很痛苦啊,干了4年了运维,是一个坎.越来越发觉想要走得远,还是得扎根底.   一.运行时数据区域 ...

  10. *新阿里镜像maven配置流程

    解决idea中maven仓库下载jar包慢的问题 配置阿里镜像 设置idea 配置阿里镜像参考链接:https://blog.csdn.net/redhat0921/article/details/1 ...