# Spring
源码 - 核心接口ObjectFactory
Spring
版本:Spring 5.3.13-release
# 1、ObjectFactory<T>
函数式接口
ObjectFactory<T>
接口源码:
@FunctionalInterface
public interface ObjectFactory<T> {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*
* 获取对象的工厂方法
*/
T getObject() throws BeansException;
}
ObjectFactory<T>
是一个对象工厂,它的功能也就不言而喻就是创建Bean
对象。
ObjectFactory<T>
中定义的getObject()
方法用于获取对象的工厂方法。
看到这个方法,有种似曾相识的感觉,没错在FactoryBean<T>
接口中定义的三个方法中也有一个是getObject()
。那么ObjectFactory<T>
函数式接口与FactoryBean<T>
接口的之间的区别与关联是什么?
# 2、FactoryBean<T>
接口
FactoryBean<T>
接口中定义了三个方法:
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
如果不了解FactoryBean<T>
接口可以查看这篇文章:Spring源码 - 核心接口FactoryBean
# 3、ObjectFactory<T>
& FactoryBean<T>
接口之间的联系
ObjectFactory<T>
与FactoryBean<T>
在功能设计上是没有什么联系的,它们最大的共同点就是都采用了工厂模式,通过工厂模式来返回一个Bean
对象。
# 4、ObjectFactory<T>
& FactoryBean<T>
接口之间的区别
FactoryBean<T>
接口的设计主要是Spring
为了对容器中Bean
的创建提供更加灵活的方式,所以FactoryBean<T>
接口着重于开发者提供定制化的Bean
创建逻辑。
在获取FactoryBean<T>
类型的Bean
实例时,Spring
对其也有特殊的获取方式。如果需要获取FactoryBean<T>
则需要使用&+beanName
拼接而成的字符串进行获取,如果要获取Bean
实例本身则直接使用beanName
获取即可。
ObjectFactory<T>
则只是一个普通的对象工厂接口。在Spring
中主要有两处使用了它:
Scope
接口中的get()
方法:
public interface Scope {
// 省略部分源码
Object get(String name, ObjectFactory<?> objectFactory);
// 省略部分源码
}
这个方法主要的目的就是从对应的域中获取到指定名称的对象,而ObjectFactory<?>
主要是为了自定义的域提供顶级拓展,而不是只仅限于request
、response
或者session
等域。
ConfigurableListableBeanFactory#registerResolvableDependency()
方法:
public interface ConfigurableListableBeanFactory
extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
// 省略部分源码
/**
* Register a special dependency type with corresponding autowired value.
* <p>This is intended for factory/context references that are supposed
* to be autowirable but are not defined as beans in the factory:
* e.g. a dependency of type ApplicationContext resolved to the
* ApplicationContext instance that the bean is living in.
* <p>Note: There are no such default types registered in a plain BeanFactory,
* not even for the BeanFactory interface itself.
* @param dependencyType the dependency type to register. This will typically
* be a base interface such as BeanFactory, with extensions of it resolved
* as well if declared as an autowiring dependency (e.g. ListableBeanFactory),
* as long as the given value actually implements the extended interface.
* @param autowiredValue the corresponding autowired value. This may also be an
* implementation of the {@link org.springframework.beans.factory.ObjectFactory}
* interface, which allows for lazy resolution of the actual target value.
*/
void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue);
// 省略部分源码
}
这个方法看似与ObjectFactory<T>
接口没有多大关联,但是仔细看Spring
提供的doc
注释。 @param autowiredValue the corresponding autowired value. This may also be an implementation of the {@link org.springframework.beans.factory.ObjectFactory}
。这是一段关于autowiredValue
的注释,从这里可以知道该方法中的dependencyType
可能就是一个ObjectFactory<T>
,其作用主要是为了能够将指定的对象进行延迟注入。在WebApplicationContextUtils#prepareBeanFactory()
方法中就有使用到该方法:
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
@Nullable ServletContext sc) {
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
if (sc != null) {
ServletContextScope appScope = new ServletContextScope(sc);
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
// Register as ServletContext attribute, for ContextCleanupListener to detect it.
sc.setAttribute(ServletContextScope.class.getName(), appScope);
}
// 手动注入各种经过 ObjectFactory 代理的类, 以保证线程安全
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
if (jsfPresent) {
FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
}
}
上面就有使用ConfigurableListableBeanFactory#registerResolvableDependency()
方法将ObjectFactory<T>
类型的实例进行延迟注入。
ResponseObjectFactory
源码:
private static class ResponseObjectFactory implements ObjectFactory<ServletResponse>, Serializable {
@Override
public ServletResponse getObject() {
ServletResponse response = currentRequestAttributes().getResponse();
if (response == null) {
throw new IllegalStateException("Current servlet response not available - " +
"consider using RequestContextFilter instead of RequestContextListener");
}
return response;
}
@Override
public String toString() {
return "Current HttpServletResponse";
}
}
当开发者在某一个类中需要注入ServletResponse
对象时,并不会直接创建一个ServletResponse
对象进行注入,而是注入一个代理类,该代理类中的方法是通过ObjectFactoryDelegatingInvocationHandler
实现的。这里需要注意的是ResponseObjectFactory
类中的getObject()
方法是从当前线程中去获取的ServletResponse
,所以这里获取的ServletResponse
是线程安全的。
AutowireUtils#ObjectFactoryDelegatingInvocationHandler
源码:
private static class ObjectFactoryDelegatingInvocationHandler implements InvocationHandler, Serializable {
private final ObjectFactory<?> objectFactory;
ObjectFactoryDelegatingInvocationHandler(ObjectFactory<?> objectFactory) {
this.objectFactory = objectFactory;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "equals":
// Only consider equal when proxies are identical.
return (proxy == args[0]);
case "hashCode":
// Use hashCode of proxy.
return System.identityHashCode(proxy);
case "toString":
return this.objectFactory.toString();
}
try {
return method.invoke(this.objectFactory.getObject(), args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
可以看到ObjectFactoryDelegatingInvocationHandler
内部会持有一个ObjectFactory<?>
,也就是刚刚说的ResponseObjectFactory
。并且会调用ObjectFactory<?>#getObject()
方法获取对象并将其进行注入,也就是上面ResponseObjectFactory
类中的getObject()
方法。所以开发者可以直接在类中注入HttpServletResponse
并且保证线程安全。
GitHub源码地址:https://github.com/kapbc/kapcb-spring-source/tree/master/Spring-Framework-v5.3.13
备注:此文为笔者学习
Spring
源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。