spring源码系列---spirngMvc

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技术应用

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值