1、HandlerMapping中的url什么时候放进去的?
以前刚开始工作的时候我记得这个源码流程大概就能说出来,网上资料也是一大堆,但是HandlerMapping中的url什么时候放进去的你真的知道么?
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean 对spring源码了解点的都知道这个方法,里面有一个初始化的过程
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// TODO 先创建Bean实例,推断构造方法入口(通过factoryBean工厂、有参数构造函数、无参数构造函数初始化)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 允许后置处理器修改合并的bean定义
// 这里的mbd为合并后的BeanDefinition
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 执行合并后的BeanDefinition后置处理器
// TODO 这里会查找@Autowired的注入点(InjectedElement)
// CommonAnnotationBeanPostProcessor 支持@BeanPostConstruct、@PreDestory、@Resource
// AutowiredAnnotationBeanPostProcessor 支持@Autowire注解和@Value注解
// BeanPostProcessor接口的典型应用
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 如果当前创建的是单例bean,并且运行循环依赖,并且还在创建中,那么则提早暴露
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 此时bean还没有完成属性注入,是一个简单的对象
// 构造一个对象工厂添加到三级缓存singletonFactories中
// 重点!!!将实例化的对象添加到singletonFactories中
// 第四次调用后置处理器
// 解决循坏依赖的核心,把原始对象放到二级缓存中,其实放的是一个Lambda表达式getEarlyBeanReference
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 对象已经暴露出去
// 在创建单例bean的时候会存在依赖注入的情况,为了避免循环依赖Spring在创建bean的时候,是不能bean创建完成就会将创建bean的ObjectFactory提早曝光
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 3、填充属性 @Autowired
// ioc DI 的过程
// 扫描注解信息,Autowired、Resource、PostConstruct、PreDestory等,反射注入对象给属性或方法参数
populateBean(beanName, mbd, instanceWrapper);
// 4、初始化
// 配置的初始化方法调用:
// InitializingBean接口afterPropertiesSet方法
// @PostConstruct注解下的方法
// 包含AOP入口
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);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// 注册bean销毁时的类 DisposableBeanAdapter
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 5、执行Aware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 6、执行初始化前
// 某些特殊方法的调用 @PostConstruct,Aware接口
// 调用BeanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 7、执行初始化
// controller处理入口
// InitializingBean接口,afterPropertiesSet方法和init-method属性调用
// 如果bean实现了InitializingBean接口,那么会直接调用afterPropertiesSet方法
// 如果<bean>节点中配置了init-method,会通过反射调用init-method指定的方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// Aop入口,有切面的实例才会被代理
if (mbd == null || !mbd.isSynthetic()) {
// 8、执行初始化后
// 调用BeanPostProcessor的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 如果bean继承自InitializingBean,直接调用其afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// controller处理入口
((InitializingBean) bean).afterPropertiesSet();
}
}
// 调用配置的init-method
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 通过反射调用init-method
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#afterPropertiesSet
注意这里的bean是 RequestMappingHandlerMapping
public void afterPropertiesSet() {
this.config = new RequestMappingInfo.BuilderConfiguration();
this.config.setUrlPathHelper(getUrlPathHelper());
this.config.setPathMatcher(getPathMatcher());
this.config.setSuffixPatternMatch(useSuffixPatternMatch());
this.config.setTrailingSlashMatch(useTrailingSlashMatch());
this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
this.config.setContentNegotiationManager(getContentNegotiationManager());
super.afterPropertiesSet();
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethods 这里遍历的是所有的bean
protected void initHandlerMethods() {
// 获取上下文中所有bean的name,不包含父容器
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
processCandidateBean(beanName);
}
}
// 日志记录HandlerMethods的总数量
handlerMethodsInitialized(getHandlerMethods());
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#processCandidateBean 这里的isHandler里面才会去筛选controller
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
try {
// 根据name找出bean的类型
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isTraceEnabled()) {
logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
}
}
// TODO 处理Controller和RequestMapping
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods
protected void detectHandlerMethods(Object handler) {
// 根据name找出bean的类型
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// 获取真实的controller,如果是代理类获取父类
Class<?> userType = ClassUtils.getUserClass(handlerType);
// 对真实的controller所有的方法进行解析和处理 key为方法对象,T为注解封装后的对象RequestMappingInfo
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
// 调用子类RequestMappingHandlerMapping的getMappingForMethod方法进行处理,即根据RequestMapping注解信息创建匹配条件RequestMappingInfo对象
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException("Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
// 找出controller中可外部调用的方法
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 注册处理方法
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#getMappingForMethod
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
// 解析方法上的requestMapping
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
// 解析方法所在类上的requestMapping
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
// 合并类和方法上的路径,比如Controller类上有@RequestMapping("/demo"),方法的@RequestMapping("/demo1"),结果为"/demo/demo1"
info = typeInfo.combine(info);
}
// 合并前缀
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#registerHandlerMethod 开始注册
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
this.mappingRegistry.register(mapping, handler, method);
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register
mapping是RequestMappingInfo对象 handler是controller类的beanName method为接口方法
public void register(T mapping, Object handler, Method method) {
// Assert that the handler method is not a suspending one.
if (KotlinDetector.isKotlinType(method.getDeclaringClass())) {
Class<?>[] parameterTypes = method.getParameterTypes();
if ((parameterTypes.length > 0) && "kotlin.coroutines.Continuation".equals(parameterTypes[parameterTypes.length - 1].getName())) {
throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
}
}
this.readWriteLock.writeLock().lock();
try {
// beanName和method封装成HandlerMethod对象
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
validateMethodMapping(handlerMethod, mapping);
this.mappingLookup.put(mapping, handlerMethod);
// 可以配置多个url
List<String> directUrls = getDirectUrls(mapping);
for (String url : directUrls) {
// url和RequestMappingInfo绑定 可以根据url找到RequestMappingInfo,再找到handlerMethod
this.urlLookup.add(url, mapping);
}
String name = null;
if (getNamingStrategy() != null) {
name = getNamingStrategy().getName(handlerMethod, mapping);
// 方法名和Method绑定
addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
// 将RequestMappingInfo url handlerMethod绑定到MappingRegistration对象 放入map
this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
}
finally {
this.readWriteLock.writeLock().unlock();
}
}
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistration#MappingRegistration
public MappingRegistration(T mapping, HandlerMethod handlerMethod,
@Nullable List<String> directUrls, @Nullable String mappingName) {
Assert.notNull(mapping, "Mapping must not be null");
Assert.notNull(handlerMethod, "HandlerMethod must not be null");
this.mapping = mapping;
this.handlerMethod = handlerMethod;
this.directUrls = (directUrls != null ? directUrls : Collections.emptyList());
this.mappingName = mappingName;
}
这里补充个东西,在springboot环境下,上面说当bean类型为RequestMappingHandlerMapping的时候才会走后面的逻辑,那么RequestMappingHandlerMapping是什么时候加到spring容器中的?
前些年还需要加@EnableWebMvc,在springboot环境下是自动配置的,进去看看这个类
典型的JavaConfig技术应用