在 Spring 框架里,FactoryBean
是一个强大且重要的特性。它允许开发者以一种更加灵活的方式来创建和管理 Bean 对象。FactoryBeanRegistrySupport
和 AbstractBeanFactory
这两个类在处理 FactoryBean
相关操作时扮演着关键角色,它们共同协作完成了 FactoryBean
的注册、对象创建以及缓存管理等功能。接下来,我们将深入剖析这些类的实现细节和背后的设计理念。
interface FactoryBean {
T getObject() throws Exception;
Class> getObjectType();
boolean isSingleton();
}
getObject()
方法:这是 FactoryBean
最核心的方法,它负责创建并返回具体的 Bean 对象。开发者可以在这个方法中编写复杂的对象创建逻辑,比如进行对象的初始化、依赖注入、资源加载等操作。例如,在一个数据库连接池的 FactoryBean
实现中,getObject()
方法可以创建并初始化一个数据库连接池实例。getObjectType()
方法:该方法用于返回 getObject()
方法所创建对象的类型。Spring 框架在运行时可以通过这个方法获取对象的类型信息,从而进行类型检查和转换。比如,在进行 Bean 注入时,Spring 可以根据 getObjectType()
返回的类型来判断是否符合注入要求。isSingleton()
方法:此方法用于指示 FactoryBean
创建的对象是否为单例。如果返回 true
,则表示该对象是单例的,Spring 会对其进行缓存,后续的请求都会返回同一个对象实例;如果返回 false
,则每次请求都会调用 getObject()
方法创建一个新的对象实例。class DefaultSingletonBeanRegistry {
private final ConcurrentMap singletonObjects = new ConcurrentHashMap<>();
protected Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
}
singletonObjects
缓存:这是一个 ConcurrentHashMap
,用于存储单例 Bean 对象。使用 ConcurrentHashMap
可以确保在多线程环境下对单例对象的访问是线程安全的,避免了并发访问时可能出现的数据不一致问题。getSingleton(String beanName)
方法:该方法用于从 singletonObjects
缓存中获取指定名称的单例 Bean 对象。如果缓存中存在该对象,则直接返回;如果不存在,则返回 null
。addSingleton(String beanName, Object singletonObject)
方法:此方法用于将一个单例 Bean 对象添加到 singletonObjects
缓存中。通过这种方式,Spring 可以在后续的请求中直接从缓存中获取该对象,而无需再次创建,提高了性能。abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
private static final Object NULL_OBJECT = new Object();
/**
* Cache of singleton objects created by FactoryBeans: FactoryBean name --> object
*/
private final ConcurrentMap factoryBeanObjectCache = new ConcurrentHashMap<>();
protected Object getCachedObjectForFactoryBean(String beanName) {
Object object = this.factoryBeanObjectCache.get(beanName);
return (object != NULL_OBJECT ? object : null);
}
protected Object getObjectFromFactoryBean(FactoryBean> factory, String beanName) {
if (factory.isSingleton()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
} else {
return doGetObjectFromFactoryBean(factory, beanName);
}
}
private Object doGetObjectFromFactoryBean(final FactoryBean> factory, final String beanName) {
try {
return factory.getObject();
} catch (Exception e) {
throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", e);
}
}
}
factoryBeanObjectCache
缓存这是一个专门用于缓存由 FactoryBean
创建的单例对象的 ConcurrentMap
。键为 FactoryBean
的名称,值为 FactoryBean
创建的对象。使用这个缓存可以避免重复创建单例对象,提高性能。
getCachedObjectForFactoryBean(String beanName)
方法该方法用于从 factoryBeanObjectCache
缓存中获取指定名称的 FactoryBean
创建的对象。如果缓存中存在该对象,则直接返回;如果缓存中存储的是 NULL_OBJECT
,则表示该对象不存在,返回 null
。
getObjectFromFactoryBean(FactoryBean> factory, String beanName)
方法这是一个核心方法,用于从 FactoryBean
中获取对象。如果 FactoryBean
创建的是单例对象,则先从 factoryBeanObjectCache
缓存中查找。如果缓存中不存在,则调用 doGetObjectFromFactoryBean
方法创建对象,并将其放入缓存中。如果 FactoryBean
创建的不是单例对象,则直接调用 doGetObjectFromFactoryBean
方法创建对象。
doGetObjectFromFactoryBean(FactoryBean> factory, String beanName)
方法该方法直接调用 FactoryBean
的 getObject()
方法来创建对象。如果创建过程中出现异常,则抛出 BeansException
异常,将异常信息和原始异常一起封装,方便后续的错误处理和调试。
abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected T doGetBean(final String name, final Object[] args) {
Object sharedInstance = getSingleton(name);
if (sharedInstance != null) {
// 如果是 FactoryBean,则需要调用 FactoryBean#getObject
return (T) getObjectForBeanInstance(sharedInstance, name);
}
BeanDefinition beanDefinition = getBeanDefinition(name);
Object bean = createBean(name, beanDefinition, args);
return (T) getObjectForBeanInstance(bean, name);
}
private Object getObjectForBeanInstance(Object beanInstance, String beanName) {
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = getCachedObjectForFactoryBean(beanName);
if (object == null) {
FactoryBean> factoryBean = (FactoryBean>) beanInstance;
object = getObjectFromFactoryBean(factoryBean, beanName);
}
return object;
}
protected abstract BeanDefinition getBeanDefinition(String name);
protected abstract Object createBean(String name, BeanDefinition beanDefinition, Object[] args);
}
doGetBean(String name, Object[] args)
方法这是获取 Bean 对象的核心方法。首先,它尝试从单例缓存中获取指定名称的 Bean 对象。如果缓存中存在该对象,则调用 getObjectForBeanInstance
方法进行处理,因为该对象可能是一个 FactoryBean
,需要进一步获取其创建的对象。如果缓存中不存在该对象,则通过 getBeanDefinition
方法获取该 Bean 的定义信息,再调用 createBean
方法创建对象,最后同样调用 getObjectForBeanInstance
方法进行处理。
getObjectForBeanInstance(Object beanInstance, String beanName)
方法该方法用于判断 beanInstance
是否为 FactoryBean
类型。如果不是,则直接返回该对象;如果是,则先从 factoryBeanObjectCache
缓存中获取 FactoryBean
创建的对象。如果缓存中不存在,则调用 getObjectFromFactoryBean
方法从 FactoryBean
中获取对象。
getBeanDefinition(String name)
和 createBean(String name, BeanDefinition beanDefinition, Object[] args)
方法这两个方法是抽象方法,需要在具体的子类中实现。getBeanDefinition
方法用于根据 Bean 的名称获取其定义信息,这些定义信息包含了 Bean 的各种属性和配置;createBean
方法用于根据 Bean 的定义信息创建具体的 Bean 对象,可能涉及到对象的实例化、属性注入、初始化等操作。
class ExampleFactoryBean implements FactoryBean {
@Override
public String getObject() throws Exception {
return "Example Object";
}
@Override
public Class> getObjectType() {
return String.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
这个类实现了 FactoryBean
接口,用于创建一个 String
类型的对象。getObject()
方法返回一个固定的字符串 "Example Object"
,表示创建的对象内容。getObjectType()
方法返回 String.class
,明确了创建对象的类型。isSingleton()
方法返回 true
,表示该对象是单例的,Spring 会对其进行缓存,后续的请求都会返回同一个 "Example Object"
实例。
public class FactoryBeanRegistrationTest {
public static void main(String[] args) {
AbstractBeanFactory beanFactory = new AbstractBeanFactory() {
@Override
protected BeanDefinition getBeanDefinition(String name) {
return new BeanDefinition();
}
@Override
protected Object createBean(String name, BeanDefinition beanDefinition, Object[] args) {
if ("exampleFactoryBean".equals(name)) {
return new ExampleFactoryBean();
}
return null;
}
};
String exampleObject = beanFactory.doGetBean("exampleFactoryBean", null);
System.out.println(exampleObject);
}
}
在这个测试类中,我们创建了一个 AbstractBeanFactory
的匿名子类,并重写了 getBeanDefinition
和 createBean
方法。getBeanDefinition
方法简单地返回一个新的 BeanDefinition
实例,实际应用中可以根据具体需求从配置文件或其他数据源中获取 Bean
的定义信息。createBean
方法根据 beanName
判断是否为 "exampleFactoryBean"
,如果是,则返回 ExampleFactoryBean
实例;否则返回 null
。然后调用 doGetBean
方法获取 ExampleFactoryBean
创建的对象,并将其打印输出。通过这个测试,我们可以验证 FactoryBean
注册服务的功能是否正常。
FactoryBean
接口本身就是工厂模式的一种体现。通过实现 FactoryBean
接口,开发者可以将对象的创建逻辑封装在 getObject()
方法中,使得对象的创建和使用分离,提高了代码的可维护性和可扩展性。FactoryBeanRegistrySupport
类中的 factoryBeanObjectCache
缓存和 DefaultSingletonBeanRegistry
类中的 singletonObjects
缓存都运用了缓存模式。缓存模式可以避免重复创建对象,提高系统的性能和响应速度。FactoryBean
来封装对象的创建逻辑。例如,创建一个数据库连接池、线程池等。FactoryBean
的 getObject()
方法中编写动态创建逻辑。例如,根据配置文件中的参数创建不同类型的日志记录器。通过对 FactoryBean
注册服务的深入分析,我们了解到 Spring 框架通过 FactoryBean
接口、FactoryBeanRegistrySupport
类和 AbstractBeanFactory
类的协作,提供了一种灵活、高效的对象创建和管理方式。FactoryBean
允许开发者自定义对象的创建逻辑,而 FactoryBeanRegistrySupport
负责对象的缓存和获取,AbstractBeanFactory
则在整个 Bean 生命周期中对 FactoryBean
进行了特殊处理。这种设计使得 Spring 框架能够满足各种复杂的应用场景,提高了系统的可维护性和可扩展性。在实际开发中,合理运用 FactoryBean
可以让我们更加灵活地管理对象的创建和使用,提升开发效率和代码质量。