Spring版本:5.1.3.RELEASE
BeanFactory
接口:
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
T getBean(String name, Class requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
T getBean(Class requiredType) throws BeansException;
T getBean(Class requiredType, Object... args) throws BeansException;
ObjectProvider getBeanProvider(Class requiredType);
ObjectProvider getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class> typeToMatch) throws NoSuchBeanDefinitionException;
Class> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
是简单工厂模式的应用,根据传入的beanName实例化相应的实例。
JavaDoc翻译(使用Google翻译并加以润色,如有歧义欢迎指出):
用于访问Spring bean容器的根接口。 这是bean容器的基本客户端视图; 其他接口(如ListableBeanFactory和org.springframework.beans.factory.config.ConfigurableBeanFactory)可用于特定目的。
该接口被一些持有bean定义的对象实现,每个bean定义由一个字符串名称唯一标识。
根据bean定义,工厂将返回包含对象的独立实例(Prototype设计模式)或单个共享实例(Singleton设计模式的高级替代,其中实例是工厂范围中的单例)。
将返回哪种类型的实例取决于bean工厂配置:API是相同的。
从Spring 2.0开始,根据具体的应用程序上下文(例如Web环境中的“request”和“session”范围),可以使用更多的scope(范围)。
这种方法的重点是BeanFactory是应用组件的注册中心和集中的配置中心(例如,不再需要单个对象去读取属性文件)。
有关此方法的优点的讨论,请参见"Expert One-on-One J2EE Design and Development"的第4章和第11章。
请注意,依靠依赖注入(“push”配置)通过setter或构造函数来配置应用对象通常更好,而不是像BeanFactory查找一样的使用“pull”配置的任意方式。Spring的依赖注入功能是使用这个BeanFactory接口及其子接口实现的。
通常,BeanFactory将加载存储在配置源(例如XML文档)中的bean定义,并使用org.springframework.beans包来配置bean。尽管如此,一种简单地实现是直接在Java代码中返回Java对象。如何存储定义没有限制:LDAP,RDBMS,XML,属性文件等。鼓励实现支持bean之间的引用(依赖注入)。
与ListableBeanFactory中的方法相反,如果这是HierarchicalBeanFactory,则此接口中的所有操作也将检查父工厂。如果在此工厂实例中找不到bean,则会询问直接父工厂(从父类bean工厂中获取)。此工厂实例中的Bean应该在任何父工厂中覆盖同名的Bean。
Bean工厂实现应尽可能支持标准bean生命周期接口。 完整的初始化方法及其标准顺序是:
关闭Bean工厂时,应用以下生命周期方法:
Spring Bean生命周期图:
Spring 4.3.17.RELEASE 源码的JavaDoc文档写的也是以上流程。跟其它网上的文章写的流程有出入,应该以官方文档为准。
FactoryBean
接口:
T getObject() throws Exception;
Class> getObjectType();
default boolean isSingleton() {
return true;
}
是工厂方法模式的应用,由子类实现相应的实例。
JavaDoc翻译(使用Google翻译并加以润色,如有歧义欢迎指出):
接口被BeanFactory中使用的对象所实现,这些对象本身就是单个对象的工厂。如果bean实现了这个接口,它将被用作暴露此对象的工厂,而不是直接将自己作为bean实例给暴露出来。
注意:实现此接口的bean不能用作普通bean。
FactoryBean是被定义成bean的形式,但是bean对象的引用(getObject()方法获得)始终是由它创建的。
FactoryBeans可以支持单例和原型,可以根据需要懒惰地创建对象,也可以在启动时急切地创建对象。
SmartFactoryBean接口允许公开更细粒度的行为元数据。
该接口在框架内部大量使用,例如用于AOP的 org.springframework.aop.framework.ProxyFactoryBean类 或 org.springframework.jndi.JndiObjectFactoryBean类。
它也可以用于定制组件;但是,这仅适用于基础架构代码。
FactoryBean是一个programatic contract (编程合约)。实现不应该依赖annotation-driven (注解驱动)的注入或其他反射设施。
getObjectType()和getObject()方法的调用可能在引导过程的早期发生,甚至在所有的(post-processor)后置处理器设置之前。
如果您需要访问其他bean,请实现 BeanFactoryAware 并以编程方式获取它们。
最后,FactoryBean对象参与包含BeanFactory的bean创建的同步。
除了FactoryBean本身(或类似)中的延迟初始化之外,通常不需要内部同步。
下面从源码层面深入分析二者区别:
查看 BeanFactory接口的抽象类 AbstractBeanFactory的getObjectForBeanInstance方法的实现:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// bean的name如果以&开头,则是FactoryBean实例
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 验证是否是FactoryBean对象,不是则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 执行到此处,已经得到了bean实例,如果是普通的bean,或者是FacoryBean实例,直接返回.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
// 从FactoryBeanObjectCache中获取由FactoryBean创建的bean对象
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// beanInstance强转为FactoryBean
FactoryBean> factory = (FactoryBean>) beanInstance;
// 如果是单例,则缓存从FactoryBean获取的对象
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 最终调用FactoryBean实例的getObject方法获取bean实例
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
在getObjectFromFactoryBean方法实现中会调用doGetObjectFromFactoryBean方法:
private Object doGetObjectFromFactoryBean(final FactoryBean> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
// 调用FactoryBean的getObject方法来返回实例
object = AccessController.doPrivileged((PrivilegedExceptionAction
实现FactoryBean的类,在初始化放入容器后,通过BeanFactory的getBean方法调用时,会调用FactoryBean的getObject方法返回对应的bean实例对象,而不是像普通的bean一样直接返回bean实例.
BeanFactory的常量&的作用是在获取bean的时候直接返回FactoryBean的bean实例,而不是调用的getObject方法返回对应的bean实例.
以上,如有问题欢迎提出!
参考: https://blog.csdn.net/silk_bar/article/details/60967064