栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring源码 - 核心接口ObjectFactory

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring源码 - 核心接口ObjectFactory

# Spring源码 - 核心接口ObjectFactory

Spring版本:Spring 5.3.13-release


# 1、ObjectFactory函数式接口

ObjectFactory接口源码:

@FunctionalInterface
public interface ObjectFactory {

	
	T getObject() throws BeansException;

}

ObjectFactory是一个对象工厂,它的功能也就不言而喻就是创建Bean对象。

ObjectFactory中定义的getObject()方法用于获取对象的工厂方法。

看到这个方法,有种似曾相识的感觉,没错在FactoryBean接口中定义的三个方法中也有一个是getObject()。那么ObjectFactory函数式接口与FactoryBean接口的之间的区别与关联是什么?


# 2、FactoryBean接口

FactoryBean接口中定义了三个方法:

public interface FactoryBean {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class getObjectType();

	default boolean isSingleton() {
		return true;
	}

}

如果不了解FactoryBean接口可以查看这篇文章:Spring源码 - 核心接口FactoryBean


# 3、ObjectFactory & FactoryBean接口之间的联系

ObjectFactory与FactoryBean在功能设计上是没有什么联系的,它们最大的共同点就是都采用了工厂模式,通过工厂模式来返回一个Bean对象。


# 4、ObjectFactory & FactoryBean接口之间的区别

FactoryBean接口的设计主要是Spring为了对容器中Bean的创建提供更加灵活的方式,所以FactoryBean接口着重于开发者提供定制化的Bean创建逻辑。

在获取FactoryBean类型的Bean实例时,Spring对其也有特殊的获取方式。如果需要获取FactoryBean则需要使用&+beanName拼接而成的字符串进行获取,如果要获取Bean实例本身则直接使用beanName获取即可。

ObjectFactory则只是一个普通的对象工厂接口。在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 {

	// 省略部分源码
    
	
	void registerResolvableDependency(Class dependencyType, @Nullable Object autowiredValue);

    // 省略部分源码
}

这个方法看似与ObjectFactory接口没有多大关联,但是仔细看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,其作用主要是为了能够将指定的对象进行延迟注入。在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类型的实例进行延迟注入。

ResponseObjectFactory源码:

	private static class ResponseObjectFactory implements ObjectFactory, 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源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。

更多Java技术笔记可扫码关注下方微信公众号。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/713046.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号