FactoryBean 的产品什么时候创建?"&" 前缀是什么?ObjectProvider 的 getIfAvailable、getIfUnique、stream 各自在没有、一个、多个候选时怎么表现?它真的是“延迟”注入吗?这篇在 Spring Framework 7.0.9 上逐项验证。
--- refresh 完成时(single)
1. 创建 FactoryBean 本体(singleton=true,getObjectType=Conn)
--- getBean("conn") 两次之后
1. 创建产品 Conn#1
getBean("conn") 的类型 Conn;getBean("&conn") 的类型 ConnFactory;两次是同一个产品?true;getBeansOfType(Conn.class).size() = 1工厂本体在 refresh 时创建,产品在第一次 getBean 时创建;"&名字" 取工厂本体。
--- refresh 完成时(proto)
1. 创建 FactoryBean 本体(singleton=false,getObjectType=Conn)
--- getBean("conn") 两次之后
1. 创建产品 Conn#1
2. 创建产品 Conn#2
getBean("conn") 的类型 Conn;getBean("&conn") 的类型 ConnFactory;两次是同一个产品?false;getBeansOfType(Conn.class).size() = 1false 时每次 getBean 调用一次 getObject。
--- refresh 完成时(eager)
1. 创建 FactoryBean 本体(singleton=true,getObjectType=Conn)
2. 创建产品 Conn#1
--- getBean("conn") 两次之后
1. 创建产品 Conn#2
2. 创建产品 Conn#3
getBean("conn") 的类型 Conn;getBean("&conn") 的类型 EagerFactory;两次是同一个产品?false;getBeansOfType(Conn.class).size() = 1SmartFactoryBean.isEagerInit 让产品也在 refresh 时创建。
--- refresh 完成时(eager2)
1. 创建 FactoryBean 本体(Eager2:直接实现 SmartFactoryBean,isSingleton 与 isEagerInit 都写成 true)
2. 创建产品 Conn#1
--- getBean("conn") 两次之后
1. 创建产品 Conn#2
2. 创建产品 Conn#3
getBean("conn") 的类型 Conn;getBean("&conn") 的类型 Eager2;两次是同一个产品?false;getBeansOfType(Conn.class).size() = 1容器不缓存 SmartFactoryBean 的产品,每次 getBean 都新建(源码注释:可能返回多种类型,不缓存)。
getObjectType() 返回 null:getBeanNamesForType(Conn.class) = [];getBean("conn") 照样能拿到 Conn;getBean(Conn.class) → NoSuchBeanDefinitionExceptiongetObjectType 返回 null 时,按名字能取到,按类型取不到。
(none)
--- refresh 完成时(none)
1. 构造 User(拿到了 ObjectProvider,还没有解析任何 Pay)
getIfAvailable() → null;getIfUnique() → null;getObject() → NoSuchBeanDefinitionException;getIfAvailable(默认) → 默认
stream() 的顺序 → [];orderedStream() 的顺序 → []
--- 上面这些调用的过程中
(one)
--- refresh 完成时(one)
1. 构造 User(拿到了 ObjectProvider,还没有解析任何 Pay)
2. 构造 P1
getIfAvailable() → p1;getIfUnique() → p1;getObject() → p1;getIfAvailable(默认) → p1
stream() 的顺序 → [p1];orderedStream() 的顺序 → [p1]
--- 上面这些调用的过程中
--- 两次 lazy.getObject()
1. 构造 Lazy1(被 ObjectProvider 引用的 prototype)
2. 构造 Lazy1(被 ObjectProvider 引用的 prototype)
(two)
--- refresh 完成时(two)
1. 构造 User(拿到了 ObjectProvider,还没有解析任何 Pay)
2. 构造 P1
3. 构造 P2
getIfAvailable() → NoUniqueBeanDefinitionException;getIfUnique() → null;getObject() → NoUniqueBeanDefinitionException;getIfAvailable(默认) → NoUniqueBeanDefinitionException
stream() 的顺序 → [p1, p2];orderedStream() 的顺序 → [p2, p1]
--- 上面这些调用的过程中没有、一个、多个候选时各取法的结果不同;它只推迟 prototype 和 @Lazy,不推迟 singleton。