springmvc HttpServletRequest和HttpServletResponse是如何注入的

在网上搜了一下具体的流程,感觉比较乱,对比源码后明白了具体的流程,在此记录一下。项目中使用了spring boot 2.7.10,对应分析过程如下。

springmvc HttpServletRequest和HttpServletResponse是如何注入的_第1张图片

 从debug信息得知,HttpServletRequest 作为全局变量进行注入和方法参数得到的类型不同。

如果是注入,获取的是处理后的代理对象。

方法参数中的类型为对应的web中 HttpServletRequest 的实现类。

由于使用的是 tomcat,发送请求时 HttpServletRequest 的实现类为 org.apache.catalina.connector.RequestFacade。

如果是 undertow,对应的实现类为 io.undertow.servlet.spec.HttpServletRequestImpl。

成员变量注入的HttpServletRequest

一句话

HttpServletRequest 每次获取不同的对象是由于 sprnig ioc 容器启动时把 HttpServletRequest 的父接口 ServletRequest 封装到 ObjectFactory 每次请求时调用AutowireUtils.resolveAutowiringValue() 生成类型为 ObjectFactory 的动态代理对象,确保每次请求的 HttpServletRequest 和 HttpServletResponse 不是同一个。

在spring中鼎鼎有名的就是AbstractApplicationContext的refresh()了。用于进行spring的一系列启动相关的操作,具体查看源码。

springmvc HttpServletRequest和HttpServletResponse是如何注入的_第2张图片

其中postProcessBeanFactory()查看对应的实现类发现都是跟web相关的。

但是与HttpServletRequest和HttpServletResponse最终有关的是spring boot里的org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext

private void registerWebApplicationScopes() {
	ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
	WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
	existingScopes.restore();
}

调用了 org.springframework.web.context.support.WebApplicationContextUtils,对应逻辑如下

public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
	registerWebApplicationScopes(beanFactory, null);
}


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);
	}

	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);
	}
}

private static class RequestObjectFactory implements ObjectFactory, Serializable {

	@Override
	public ServletRequest getObject() {
		return currentRequestAttributes().getRequest();
	}

	@Override
	public String toString() {
		return "Current HttpServletRequest";
	}
}

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";
	}
}

通过 beanFactory.registerResolvableDependency() 注册对应的接口类型和以及对应的 ObjectFactory 实现。

依赖注入开始

org.springframework.beans.factory.support.AbstractBeanFactory

public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}

protected  T doGetBean(
		String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)
		throws BeansException {

	String beanName = transformedBeanName(name);
	Object beanInstance;

			// Create bean instance.
			if (mbd.isSingleton()) {
				sharedInstance = getSingleton(beanName, () -> {
					try {
						return createBean(beanName, mbd, args);
					}
					catch (BeansException ex) {
						// Explicitly remove instance from singleton cache: It might have been put there
						// eagerly by the creation process, to allow for circular reference resolution.
						// Also remove any beans that received a temporary reference to the bean.
						destroySingleton(beanName);
						throw ex;
					}
				});
				beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}

			else if (mbd.isPrototype()) {
				// It's a prototype -> create a new instance.
				Object prototypeInstance = null;
				try {
					beforePrototypeCreation(beanName);
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					afterPrototypeCreation(beanName);
				}
				beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}

			
	}

	return adaptBeanInstance(name, beanInstance, requiredType);
}

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException;

createBean() 调用实现类 AbstractAutowireCapableBeanFactory 实现逻辑

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {

	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	Class resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	try {
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		// A previously detected exception with proper bean creation context already,
		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {

	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	Object bean = instanceWrapper.getWrappedInstance();
	Class beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		populateBean(beanName, mbd, instanceWrapper);
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}

	// Register bean as disposable.
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
}

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	

	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

	int resolvedAutowireMode = mbd.getResolvedAutowireMode();
	if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
		// Add property values based on autowire by name if applicable.
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}
		// Add property values based on autowire by type if applicable.
		if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			autowireByType(beanName, mbd, bw, newPvs);
		}
		pvs = newPvs;
	}

	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
			if (pvsToUse == null) {
				if (filteredPds == null) {
					filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
				}
				pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					return;
				}
			}
			pvs = pvsToUse;
		}
	}
	if (needsDepCheck) {
		if (filteredPds == null) {
			filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
		}
		checkDependencies(beanName, mbd, filteredPds, pvs);
	}

	if (pvs != null) {
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

因为注入使用的注解是 javax.annotation.Resource,此注解默认由 CommonAnnotationBeanPostProcessor 处理,是 InstantiationAwareBeanPostProcessor 的实现类,调用 postProcessProperties() 执行对应的逻辑。

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
	try {
		metadata.inject(bean, beanName, pvs);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
	}
	return pvs;
}

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
		throws NoSuchBeanDefinitionException {

	// JNDI lookup to perform?
	String jndiName = null;
	if (StringUtils.hasLength(element.mappedName)) {
		jndiName = element.mappedName;
	}
	else if (this.alwaysUseJndiLookup) {
		jndiName = element.name;
	}
	if (jndiName != null) {
		if (this.jndiFactory == null) {
			throw new NoSuchBeanDefinitionException(element.lookupType,
					"No JNDI factory configured - specify the 'jndiFactory' property");
		}
		return this.jndiFactory.getBean(jndiName, element.lookupType);
	}

	return autowireResource(this.resourceFactory, element, requestingBeanName);
}


protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
		throws NoSuchBeanDefinitionException {

	Object resource;
	Set autowiredBeanNames;
	String name = element.name;

	if (factory instanceof AutowireCapableBeanFactory) {
		AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
		DependencyDescriptor descriptor = element.getDependencyDescriptor();
		if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
			autowiredBeanNames = new LinkedHashSet<>();
			resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
			if (resource == null) {
				throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
			}
		}
		else {
			resource = beanFactory.resolveBeanByName(name, descriptor);
			autowiredBeanNames = Collections.singleton(name);
		}
	}
	else {
		resource = factory.getBean(name, element.lookupType);
		autowiredBeanNames = Collections.singleton(name);
	}

	if (factory instanceof ConfigurableBeanFactory) {
		ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
		for (String autowiredBeanName : autowiredBeanNames) {
			if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
				beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
			}
		}
	}

	return resource;
}

resolveDependency() 调用 DefaultListableBeanFactory 对应的方法执行逻辑。

org.springframework.beans.factory.support.DefaultListableBeanFactory

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
		@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
	if (Optional.class == descriptor.getDependencyType()) {
		return createOptionalDependency(descriptor, requestingBeanName);
	}
	else if (ObjectFactory.class == descriptor.getDependencyType() ||
			ObjectProvider.class == descriptor.getDependencyType()) {
		return new DependencyObjectProvider(descriptor, requestingBeanName);
	}
	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
		return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
	}
	else {
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
	}
}

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
			return shortcut;
		}

		Class type = descriptor.getDependencyType();

		Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;

		if (matchingBeans.size() > 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
					return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
				}
				else {
					// In case of an optional Collection/Map, silently ignore a non-unique case:
					// possibly it was meant to be an empty collection of multiple regular beans
					// (before 4.3 in particular when we didn't even look for collection beans).
					return null;
				}
			}
			instanceCandidate = matchingBeans.get(autowiredBeanName);
		}
		else {
			// We have exactly one match.
			Map.Entry entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		if (instanceCandidate instanceof Class) {
			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
		}
		Object result = instanceCandidate;
		if (result instanceof NullBean) {
			if (isRequired(descriptor)) {
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			result = null;
		}
		if (!ClassUtils.isAssignableValue(type, result)) {
			throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
		}
		return result;
	}
	finally {
		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
	}
}

protected Map findAutowireCandidates(
		@Nullable String beanName, Class requiredType, DependencyDescriptor descriptor) {

	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
	Map result = CollectionUtils.newLinkedHashMap(candidateNames.length);
	for (Map.Entry, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
		Class autowiringType = classObjectEntry.getKey();
		if (autowiringType.isAssignableFrom(requiredType)) {
			Object autowiringValue = classObjectEntry.getValue();
			autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
			if (requiredType.isInstance(autowiringValue)) {
				result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
				break;
			}
		}
	}
	
	return result;
}

springmvc HttpServletRequest和HttpServletResponse是如何注入的_第3张图片 findAutowireCandidates() 中调试参数

各个参数值如下

requiredType

interface javax.servlet.http.HttpServletRequest

autowiringType

interface javax.servlet.ServletRequest

autowiringValue


调用 AutowireUtils.resolveAutowiringValue() 前

WebApplicationContextUtils.RequestObjectFactory

调用 AutowireUtils.resolveAutowiringValue() 后

$Proxy

h
AutowireUtils.ObjectFactoryDelegatingInvocationHandler

objectFactory
WebApplicationContextUtils.RequestObjectFactory
 

调用后 WebApplicationContextUtils.RequestObjectFactory 作为 AutowireUtils.ObjectFactoryDelegatingInvocationHandler 的一个成员变量进行保存。这样获取的就是一个 ObjectFactory,每次调用都会返回一个新实例。

org.springframework.beans.factory.support.AutowireUtils

public static Object resolveAutowiringValue(Object autowiringValue, Class requiredType) {
	if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) {
		ObjectFactory factory = (ObjectFactory) autowiringValue;
		if (autowiringValue instanceof Serializable && requiredType.isInterface()) {
			autowiringValue = Proxy.newProxyInstance(requiredType.getClassLoader(),
					new Class[] {requiredType}, new ObjectFactoryDelegatingInvocationHandler(factory));
		}
		else {
			return factory.getObject();
		}
	}
	return autowiringValue;
}

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();
		}
	}
}

通过 java 的动态代理调用 ObjectFactory 来生成对应的对象。

web请求映射的方法的 HttpServletRequest 参数

通过普通发送请求的方式获取 HttpServletRequest 对象

springmvc HttpServletRequest和HttpServletResponse是如何注入的_第4张图片 springmvc请求流程

org.springframework.web.servlet.FrameworkServlet



protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

	long startTime = System.currentTimeMillis();
	Throwable failureCause = null;

	LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
	LocaleContext localeContext = buildLocaleContext(request);

	RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
	ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
	asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

	initContextHolders(request, localeContext, requestAttributes);

	try {
		doService(request, response);
	}
	catch (ServletException | IOException ex) {
		failureCause = ex;
		throw ex;
	}
	catch (Throwable ex) {
		failureCause = ex;
		throw new NestedServletException("Request processing failed", ex);
	}

	finally {
		resetContextHolders(request, previousLocaleContext, previousAttributes);
		if (requestAttributes != null) {
			requestAttributes.requestCompleted();
		}
		logResult(request, response, failureCause, asyncManager);
		publishRequestHandledEvent(request, response, startTime, failureCause);
	}
}

private void initContextHolders(HttpServletRequest request,
		@Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) {

	if (localeContext != null) {
		LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
	}
	if (requestAttributes != null) {
		RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
	}
}

private void resetContextHolders(HttpServletRequest request,
		@Nullable LocaleContext prevLocaleContext, @Nullable RequestAttributes previousAttributes) {

	LocaleContextHolder.setLocaleContext(prevLocaleContext, this.threadContextInheritable);
	RequestContextHolder.setRequestAttributes(previousAttributes, this.threadContextInheritable);
}

一句话

将 HttpServletRequest 和 HttpServletResponse 封装为 ServletRequestAttributes 传入 initContextHolders() 为 RequestContextHolder 中的 ThreadLocal 进行赋值,最后调用 resetContextHolders() 将 RequestContextHolder 中的 ThreadLocal 清空。

org.springframework.web.context.request.RequestContextHolder



public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {
	if (attributes == null) {
		resetRequestAttributes();
	}
	else {
		if (inheritable) {
			inheritableRequestAttributesHolder.set(attributes);
			requestAttributesHolder.remove();
		}
		else {
			requestAttributesHolder.set(attributes);
			inheritableRequestAttributesHolder.remove();
		}
	}
}


public static void resetRequestAttributes() {
	requestAttributesHolder.remove();
	inheritableRequestAttributesHolder.remove();
}

由此可知,无论是注入方式获取对应的 HttpServletRequest 和 HttpServletResponse 还是方法参数的方式获取,都是在 FrameworkServlet 中调用 RequestContextHolder 进行赋值和清空。

参考链接

https://www.cnblogs.com/kevin-yuan/p/5336124.html

https://www.cnblogs.com/abcwt112/p/7777258.html

https://blog.51cto.com/u_13270529/5962186

你可能感兴趣的:(java,java)