Spring源码 - 核心接口ObjectFactory

# 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<?>主要是为了自定义的域提供顶级拓展,而不是只仅限于requestresponse或者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源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值