文章目录
前言
之前我在这篇文章说过Spring往容器里管理了Request对象,所以你可以在spring的任何实例里面注入HTTPRequest对象。具体是怎么实现的呢?
今天就来更详细地分析下~
一、来个例子
public class HealthController {
@Resource
private HttpServletRequest request;
@ApiOperation("健康检查")
@GetMapping("check")
public String health() {
System.out.println(request);
System.out.println(request.getRequestURI());
return "OK";
}
}
为了测试,在我们的健康检查接口类里注入了request对象,同时在健康检查的接口里打印信息
接口调用之后,打印结果如下
Current HttpServletRequest
/xxxxx/api/health/check
如果不想通过注入方式,也可以通过((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest()拿到咱们的request对象。
二、解析一下
1. 为啥会打印Current HttpServletRequest
想想,我们给Spring注入的ServletRequest对象是什么
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
我们再来看看这个RequestObjectFactory类
@SuppressWarnings("serial")
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {
@Override
public ServletRequest getObject() {
return currentRequestAttributes().getRequest();
}
@Override
public String toString() {
return "Current HttpServletRequest";
}
}
可以看到toString()方法的返回,也就是咱们的打印
2. 既然是Spring注入的对象,为啥能做到动态变化
其实此处很容易想到动态代理,毕竟整个Spring的AOP都是基于动态代理做的,但是这个动态代理却又是如此特殊,多数情况下,我们的动态代理不过是在实现invoke()的时候,在target.method调用前后加上咱们的私有逻辑。
但是注意此处Spring给该Request注入的是个RequestObjectFactory,也不是动态代理对象啊。别着急,咱们看看Spring给咱们实际在注入的时候是怎么处理的。
通过添加断点,我们可以发现,在request进行注入的时候,走了以下的逻辑:
/**
* Resolve the given autowiring value against the given required type,
* e.g. an {@link ObjectFactory} value to its actu