当前位置: 首页 > article >正文

Spring源码中的工具类

文章目录

  • spring-core
    • StandardAnnotationMetadata 取类描述信息
    • AnnotatedElementUtils、AnnotationUtils查找类注释
    • DefaultConversionService 默认转换器,设包含一组类型转换器
    • SimpleCommandLineArgsParser 简单的解析命令行数据
    • JOptCommandLinePropertySource 扩展自CommandLinePropertySource解析命令行参数
    • MutablePropertySources 包含一组资源文件,可以设置顺序
    • ResourceUtils 加载资源
    • StylerUtils 指定toString的打印格式
    • SimpleMetadataReaderFactory 读取元数据,5.2新加
    • AnnotationTypeFilter 判断指定类是否有某个注解
    • AspectJTypeFilter 判断类和指定描述是否一致
    • ExceptionDepthComparator 异常深度比较器
    • StopWatch 秒表,监视任务性能耗时
    • StreamUtils FileCopyUtils FileSystemUtils 流、文件操作
    • GenericTypeResolver 解析泛型
  • spring-beans
    • SimpleBeanDefinitionRegistry BeanDefinitionRegistry接口的简单实现
    • BeanExpressionContext 上下文对象,用于对bean定义中的表达式求值
    • PropertyResourceConfigurer 实现了BeanFactoryPostProcessor,可以在Bean定义时修改值
    • PropertyPlaceholderConfigurer 继承PropertyResourceConfigurer,解析占位符,5.2已启用
    • YamlPropertiesFactoryBean 解析yml文件
    • CustomEditorConfigurer 实现了BeanFactoryPostProcessor,可以自定义编辑器,改包下还有大量其他编辑器
    • PropertyEditorRegistrySupport PropertyEditorRegistry接口的基本实现。提供对默认编辑器和自定义编辑器的管理。主要用作BeanWrapperImpl的基类
    • TypeConverterDelegate 类型转换为指定类型的助手类,由BeanWrapperImpl和SimpleTypeConverter调用
    • BeanUtils 对象复制、实例化、方法查找、属性描述等
    • ArgumentConvertingMethodInvoker 通过参数调用方法,支持重载
    • PagedListHolder 将对象以分页形式展示
    • BeanWrapperImpl 包装指定类
    • CachedIntrospectionResults 缓存PropertyDescriptor,不建议应用程序使用
    • ExtendedBeanInfoFactory、ExtendedBeanInfo 解决链式调用问题
    • MutablePropertyValues PropertyValues的简单实现
    • BeanDefinitionBuilder 构建BeanDefinition
    • BeanDefinitionReaderUtils 注册bean
    • PropertyAccessorUtils bean属性访问
  • spring-aop
    • AnnotationAwareAspectJAutoProxyCreator @Aspect动态创建代理
    • AopProxyUtils
      • completeProxiedInterfaces(AdvisedSupport advised)
  • spring-context
    • ConfigurationClassPostProcessor 扫描注解,进行注册bean
    • ConfigurationClassParser 解析@Configuration的注解类
    • ConfigurationClassEnhancer 代理增强@Configuration修饰的类,实现对@Bean发现的拦截
    • PostProcessorRegistrationDelegate AbstractApplicationContext的后处理器处理的委托。
    • StandardBeanExpressionResolver spEl表达式解析
    • ResourceEditorRegistrar 添加资源编码器,对URL\File等资源解析
    • AnnotationMetadata.introspect(class) 自省方式获取bean
    • AnnotationConfigUtils.attributesFor(metadata, Bean.class) 获取bean注释信息
    • AnnotationConfigUtils 配置了大量和注释相关的上下信息,AnnotationConfigApplicationContext回去使用
  • spring-webmvc
    • RequestMappingHandlerAdapter

spring-core

整合了asm和cglib包,并定制了部分功能

StandardAnnotationMetadata 取类描述信息

根据注解生成AnnotatedGenericBeanDefinition时很有用

 StandardAnnotationMetadata.from(type);

AnnotatedElementUtils、AnnotationUtils查找类注释

Method m = Leaf.class.getMethod("annotatedOnLeaf");
assertThat(m.getAnnotation(Order.class)).isNotNull();
assertThat(AnnotationUtils.getAnnotation(m, Order.class)).isNotNull();
assertThat(AnnotationUtils.findAnnotation(m, Order.class)).isNotNull();

DefaultConversionService 默认转换器,设包含一组类型转换器

assertThat(conversionService.convert("false", Boolean.class)).isEqualTo(false);
assertThat(conversionService.convert("off", Boolean.class)).isEqualTo(false);
assertThat(conversionService.convert("no", Boolean.class)).isEqualTo(false);
assertThat(conversionService.convert("0", Boolean.class)).isEqualTo(false);
assertThat(conversionService.convert("FALSE", Boolean.class)).isEqualTo(false);
assertThat(conversionService.convert("OFF", Boolean.class)).isEqualTo(false);
assertThat(conversionService.convert("NO", Boolean.class)).isEqualTo(false);

SimpleCommandLineArgsParser 简单的解析命令行数据

final SimpleCommandLineArgsParser parser = new SimpleCommandLineArgsParser();
CommandLineArgs args = parser.parse("--o1");
assertThat(args.containsOption("o1")).isTrue();
assertThat(args.getOptionValues("o1")).isEqualTo(Collections.EMPTY_LIST);

JOptCommandLinePropertySource 扩展自CommandLinePropertySource解析命令行参数


@Test
void withRequiredArg_andMultipleArgsPresent_usingDelimiter() {OptionParser parser = new OptionParser();parser.accepts("foo").withRequiredArg().withValuesSeparatedBy(',');OptionSet options = parser.parse("--foo=bar,baz,biz");CommandLinePropertySource<?> ps = new JOptCommandLinePropertySource(options);assertThat(ps.getOptionValues("foo")).containsExactly("bar", "baz", "biz");assertThat(ps.getProperty("foo")).isEqualTo("bar,baz,biz");
}@Test
void withRequiredArg_andMultipleArgsPresent_usingRepeatedOption() {OptionParser parser = new OptionParser();parser.accepts("foo").withRequiredArg().withValuesSeparatedBy(',');OptionSet options = parser.parse("--foo=bar", "--foo=baz", "--foo=biz");CommandLinePropertySource<?> ps = new JOptCommandLinePropertySource(options);assertThat(ps.getOptionValues("foo")).containsExactly("bar", "baz", "biz");assertThat(ps.getProperty("foo")).isEqualTo("bar,baz,biz");
}

MutablePropertySources 包含一组资源文件,可以设置顺序

MutablePropertySources sources = new MutablePropertySources();
sources.addLast(new MockPropertySource("b").withProperty("p1", "bValue"));
sources.addLast(new MockPropertySource("d").withProperty("p1", "dValue"));
sources.addLast(new MockPropertySource("f").withProperty("p1", "fValue"));assertThat(sources.size()).isEqualTo(3);
assertThat(sources.contains("a")).isFalse();
assertThat(sources.contains("b")).isTrue();
assertThat(sources.contains("c")).isFalse();
assertThat(sources.contains("d")).isTrue();
assertThat(sources.contains("e")).isFalse();
assertThat(sources.contains("f")).isTrue();
assertThat(sources.contains("g")).isFalse();assertThat(sources.get("b")).isNotNull();
assertThat(sources.get("b").getProperty("p1")).isEqualTo("bValue");
assertThat(sources.get("d")).isNotNull();
assertThat(sources.get("d").getProperty("p1")).isEqualTo("dValue");sources.addBefore("b", new MockPropertySource("a"));
sources.addAfter("b", new MockPropertySource("c"));

ResourceUtils 加载资源

StylerUtils 指定toString的打印格式

SimpleMetadataReaderFactory 读取元数据,5.2新加

MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(AnnotatedComponentSubClass.class.getName());
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(AnnotatedComponent.class.getName());
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
assertThat(metadata.getClassName()).isEqualTo(AnnotatedComponent.class.getName());
assertThat(metadata.isInterface()).isFalse();
assertThat(metadata.isAnnotation()).isFalse();
assertThat(metadata.isAbstract()).isFalse();
assertThat(metadata.isConcrete()).isTrue();
assertThat(metadata.hasSuperClass()).isTrue();
assertThat(metadata.getSuperClassName()).isEqualTo(Object.class.getName());
assertThat(metadata.getInterfaceNames().length).isEqualTo(1);
assertThat(metadata.getInterfaceNames()[0]).isEqualTo(Serializable.class.getName());assertThat(metadata.isAnnotated(Component.class.getName())).isTrue();assertThat(metadata.isAnnotated(NamedComposedAnnotation.class.getName())).isTrue();assertThat(metadata.hasAnnotation(Component.class.getName())).isTrue();
assertThat(metadata.hasAnnotation(Scope.class.getName())).isTrue();
assertThat(metadata.hasAnnotation(SpecialAttr.class.getName())).isTrue();
Set<MethodMetadata> methods = classMetadata.getAnnotatedMethods(TestAutowired.class.getName());
assertThat(methods).hasSize(1);
for (MethodMetadata methodMetadata : methods) {assertThat(methodMetadata.isAnnotated(TestAutowired.class.getName())).isTrue();
}

AnnotationTypeFilter 判断指定类是否有某个注解

MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
String classUnderTest = "example.type.AnnotationTypeFilterTestsTypes$SomeSubclassOfSomeComponent";
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classUnderTest);AnnotationTypeFilter filter = new AnnotationTypeFilter(InheritedAnnotation.class);
assertThat(filter.match(metadataReader, metadataReaderFactory)).isTrue();
ClassloadingAssertions.assertClassNotLoaded(classUnderTest);

AspectJTypeFilter 判断类和指定描述是否一致

String type = "example.type.AspectJTypeFilterTestsTypes$SomeClass";
String typePattern = "example.type.AspectJTypeFilterTestsTypes.SomeClassX";
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(type);AspectJTypeFilter filter = new AspectJTypeFilter(typePattern, getClass().getClassLoader());
assertThat(filter.match(metadataReader, metadataReaderFactory)).isFalse();
ClassloadingAssertions.assertClassNotLoaded(type);

ExceptionDepthComparator 异常深度比较器

Class<? extends Throwable> foundClass = ExceptionDepthComparator.findClosestMatch(Arrays.asList(SameDepthException.class, TargetException.class), new TargetException());
assertThat(foundClass).isEqualTo(TargetException.class);

StopWatch 秒表,监视任务性能耗时

StreamUtils FileCopyUtils FileSystemUtils 流、文件操作

InputStream inputStream = spy(new ByteArrayInputStream(bytes));
byte[] actual = StreamUtils.copyToByteArray(inputStream);Charset charset = Charset.defaultCharset();
InputStream inputStream = spy(new ByteArrayInputStream(string.getBytes(charset)));
String actual = StreamUtils.copyToString(inputStream, charset);ByteArrayInputStream in = new ByteArrayInputStream(content);
ByteArrayOutputStream out = new ByteArrayOutputStream(content.length);
int count = FileCopyUtils.copy(in, out);String content = "content";
StringReader in = new StringReader(content);
StringWriter out = new StringWriter();
int count = FileCopyUtils.copy(in, out);String content = "content";
StringWriter out = new StringWriter();
FileCopyUtils.copy(content, out);String content = "content";
StringReader in = new StringReader(content);
String result = FileCopyUtils.copyToString(in);File src = new File("./tmp/src");
File child = new File(src, "child");
File grandchild = new File(child, "grandchild");grandchild.mkdirs();File bar = new File(child, "bar.txt");
bar.createNewFile();assertThat(src.exists()).isTrue();
assertThat(child.exists()).isTrue();
assertThat(grandchild.exists()).isTrue();
assertThat(bar.exists()).isTrue();File dest = new File("./dest");
FileSystemUtils.copyRecursively(src, dest);assertThat(dest.exists()).isTrue();
assertThat(new File(dest, child.getName()).exists()).isTrue();FileSystemUtils.deleteRecursively(src);

GenericTypeResolver 解析泛型

map = GenericTypeResolver.getTypeVariableMap(MySimpleInterfaceType.class);
assertThat(map.toString()).isEqualTo("{T=class java.lang.String}");map = GenericTypeResolver.getTypeVariableMap(MyCollectionInterfaceType.class);
assertThat(map.toString()).isEqualTo("{T=java.util.Collection<java.lang.String>}");

spring-beans

依赖spring-core

SimpleBeanDefinitionRegistry BeanDefinitionRegistry接口的简单实现

只提供注册表功能,没有内置的工厂功能。例如,可以用于测试bean定义读取器

BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(ComponentWithName.class);
String beanName = this.beanNameGenerator.generateBeanName(bd, registry);
assertThat(beanName).as("The generated beanName must *never* be null.").isNotNull();
assertThat(StringUtils.hasText(beanName)).as("The generated beanName must *never* be blank.").isTrue();
assertThat(beanName).isEqualTo("walden");

BeanExpressionContext 上下文对象,用于对bean定义中的表达式求值

PropertyResourceConfigurer 实现了BeanFactoryPostProcessor,可以在Bean定义时修改值

PropertyPlaceholderConfigurer 继承PropertyResourceConfigurer,解析占位符,5.2已启用

5.2后推荐使用 PropertySourcesPlaceholderConfigurer

DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition());
builder.beanDefinition.setBeanClass(TestBean.class);bf.registerBeanDefinition("testBean",builder.addPropertyValue("name", "${my.name}").getBeanDefinition());PropertyPlaceholderConfigurer pc = new PropertyPlaceholderConfigurer();Resource resource = new ClassPathResource("PropertyPlaceholderConfigurerTests.properties", this.getClass());pc.setLocation(resource);pc.postProcessBeanFactory(bf);

YamlPropertiesFactoryBean 解析yml文件

YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(new ByteArrayResource("foo: bar\nspam:\n  foo: baz".getBytes()));
Properties properties = factory.getObject();
assertThat(properties.getProperty("foo")).isEqualTo("bar");
assertThat(properties.getProperty("spam.foo")).isEqualTo("baz");

CustomEditorConfigurer 实现了BeanFactoryPostProcessor,可以自定义编辑器,改包下还有大量其他编辑器

DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
CustomEditorConfigurer cec = new CustomEditorConfigurer();
final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
cec.setPropertyEditorRegistrars(new PropertyEditorRegistrar[] {new PropertyEditorRegistrar() {@Overridepublic void registerCustomEditors(PropertyEditorRegistry registry) {registry.registerCustomEditor(Date.class, new CustomDateEditor(df, true));}}});
cec.postProcessBeanFactory(bf);MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("date", "2.12.1975");
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
bd1.setPropertyValues(pvs);
bf.registerBeanDefinition("tb1", bd1);
pvs = new MutablePropertyValues();
pvs.add("someMap[myKey]", new TypedStringValue("2.12.1975", Date.class));
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
bd2.setPropertyValues(pvs);
bf.registerBeanDefinition("tb2", bd2);TestBean tb1 = (TestBean) bf.getBean("tb1");
assertThat(tb1.getDate()).isEqualTo(df.parse("2.12.1975"));
TestBean tb2 = (TestBean) bf.getBean("tb2");
assertThat(tb2.getSomeMap().get("myKey")).isEqualTo(df.parse("2.12.1975"));

PropertyEditorRegistrySupport PropertyEditorRegistry接口的基本实现。提供对默认编辑器和自定义编辑器的管理。主要用作BeanWrapperImpl的基类

@Nullable
public PropertyEditor getDefaultEditor(Class<?> requiredType) {if (!this.defaultEditorsActive) {return null;}if (this.overriddenDefaultEditors != null) {PropertyEditor editor = this.overriddenDefaultEditors.get(requiredType);if (editor != null) {return editor;}}if (this.defaultEditors == null) {// 核心,懒加载所有编辑器createDefaultEditors();}return this.defaultEditors.get(requiredType);
}private void createDefaultEditors() {this.defaultEditors = new HashMap<>(64);// Simple editors, without parameterization capabilities.// The JDK does not contain a default editor for any of these target types.this.defaultEditors.put(Charset.class, new CharsetEditor());this.defaultEditors.put(Class.class, new ClassEditor());this.defaultEditors.put(Class[].class, new ClassArrayEditor());this.defaultEditors.put(Currency.class, new CurrencyEditor());this.defaultEditors.put(File.class, new FileEditor());this.defaultEditors.put(InputStream.class, new InputStreamEditor());this.defaultEditors.put(InputSource.class, new InputSourceEditor());this.defaultEditors.put(Locale.class, new LocaleEditor());this.defaultEditors.put(Path.class, new PathEditor());
.....}

TypeConverterDelegate 类型转换为指定类型的助手类,由BeanWrapperImpl和SimpleTypeConverter调用

内部保存了 PropertyEditorRegistrySupport

BeanUtils 对象复制、实例化、方法查找、属性描述等

ArgumentConvertingMethodInvoker 通过参数调用方法,支持重载

ArgumentConvertingMethodInvoker methodInvoker = new ArgumentConvertingMethodInvoker();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArgument");
methodInvoker.setArguments(5);
methodInvoker.prepare();
methodInvoker.invoke();methodInvoker = new ArgumentConvertingMethodInvoker();
methodInvoker.setTargetClass(TestClass1.class);
methodInvoker.setTargetMethod("intArgument");
methodInvoker.setArguments(5);
methodInvoker.prepare();
methodInvoker.invoke();

PagedListHolder 将对象以分页形式展示

BeanWrapperImpl 包装指定类

BeanWrapper bw = new BeanWrapperImpl(TestBean.class);
assertThat(bw.isWritableProperty("name")).isTrue();
assertThat(bw.isWritableProperty("age")).isTrue();

CachedIntrospectionResults 缓存PropertyDescriptor,不建议应用程序使用

BeanWrapper bw = new BeanWrapperImpl(TestBean.class);
assertThat(bw.isWritableProperty("name")).isTrue();
assertThat(bw.isWritableProperty("age")).isTrue();
assertThat(CachedIntrospectionResults.strongClassCache.containsKey(TestBean.class)).isTrue();ClassLoader child = new OverridingClassLoader(getClass().getClassLoader());
Class<?> tbClass = child.loadClass("org.springframework.beans.testfixture.beans.TestBean");
assertThat(CachedIntrospectionResults.strongClassCache.containsKey(tbClass)).isFalse();
CachedIntrospectionResults.acceptClassLoader(child);
bw = new BeanWrapperImpl(tbClass);
assertThat(bw.isWritableProperty("name")).isTrue();
assertThat(bw.isWritableProperty("age")).isTrue();
assertThat(CachedIntrospectionResults.strongClassCache.containsKey(tbClass)).isTrue();
CachedIntrospectionResults.clearClassLoader(child);
assertThat(CachedIntrospectionResults.strongClassCache.containsKey(tbClass)).isFalse();assertThat(CachedIntrospectionResults.strongClassCache.containsKey(TestBean.class)).isTrue();

ExtendedBeanInfoFactory、ExtendedBeanInfo 解决链式调用问题

MutablePropertyValues PropertyValues的简单实现

TestBean target = new TestBean();
String newName = "tony";
String invalidTouchy = ".valid";
BeanWrapper accessor = createAccessor(target);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValue(new PropertyValue("age", "foobar"));
pvs.addPropertyValue(new PropertyValue("name", newName));
pvs.addPropertyValue(new PropertyValue("touchy", invalidTouchy));
assertThatExceptionOfType(PropertyBatchUpdateException.class).isThrownBy(() ->accessor.setPropertyValues(pvs)).satisfies(ex -> {assertThat(ex.getExceptionCount()).isEqualTo(2);assertThat(ex.getPropertyAccessException("touchy").getPropertyChangeEvent().getNewValue()).isEqualTo(invalidTouchy);});
// Test validly set property matches
assertThat(target.getName().equals(newName)).as("Valid set property must stick").isTrue();
assertThat(target.getAge() == 0).as("Invalid set property must retain old value").isTrue();

BeanDefinitionBuilder 构建BeanDefinition

BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
bdb.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bdb.addPropertyValue("age", "15");
for (String dependsOnEntry : dependsOn) {bdb.addDependsOn(dependsOnEntry);
}RootBeanDefinition rbd = (RootBeanDefinition) bdb.getBeanDefinition();

BeanDefinitionReaderUtils 注册bean

BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, beanName);
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);

PropertyAccessorUtils bean属性访问

spring-aop

依赖spring-core、spring-beans

AnnotationAwareAspectJAutoProxyCreator @Aspect动态创建代理

AopProxyUtils

completeProxiedInterfaces(AdvisedSupport advised)

为代理对象添加标记接口

boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));

spring-context

ConfigurationClassPostProcessor 扫描注解,进行注册bean

ConfigurationClassParser 解析@Configuration的注解类

ConfigurationClassEnhancer 代理增强@Configuration修饰的类,实现对@Bean发现的拦截

PostProcessorRegistrationDelegate AbstractApplicationContext的后处理器处理的委托。

StandardBeanExpressionResolver spEl表达式解析

ResourceEditorRegistrar 添加资源编码器,对URL\File等资源解析

AnnotationMetadata.introspect(class) 自省方式获取bean

AnnotationConfigUtils.attributesFor(metadata, Bean.class) 获取bean注释信息

AnnotationConfigUtils 配置了大量和注释相关的上下信息,AnnotationConfigApplicationContext回去使用

spring-webmvc

RequestMappingHandlerAdapter

afterPropertiesSet 初始mvc常用的参数解析器,初始参数解析器和返回参数解析器

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();// Annotation-based argument resolutionresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));resolvers.add(new RequestParamMapMethodArgumentResolver());resolvers.add(new PathVariableMethodArgumentResolver());resolvers.add(new PathVariableMapMethodArgumentResolver());resolvers.add(new MatrixVariableMethodArgumentResolver());resolvers.add(new MatrixVariableMapMethodArgumentResolver());resolvers.add(new ServletModelAttributeMethodProcessor(false));resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));resolvers.add(new RequestHeaderMapMethodArgumentResolver());resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new SessionAttributeMethodArgumentResolver());resolvers.add(new RequestAttributeMethodArgumentResolver());// Type-based argument resolutionresolvers.add(new ServletRequestMethodArgumentResolver());resolvers.add(new ServletResponseMethodArgumentResolver());resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RedirectAttributesMethodArgumentResolver());resolvers.add(new ModelMethodProcessor());resolvers.add(new MapMethodProcessor());resolvers.add(new ErrorsMethodArgumentResolver());resolvers.add(new SessionStatusMethodArgumentResolver());resolvers.add(new UriComponentsBuilderMethodArgumentResolver());// Custom argumentsif (getCustomArgumentResolvers() != null) {resolvers.addAll(getCustomArgumentResolvers());}// Catch-allresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));resolvers.add(new ServletModelAttributeMethodProcessor(true));return resolvers;}/*** Return the list of argument resolvers to use for {@code @InitBinder}* methods including built-in and custom resolvers.*/private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();// Annotation-based argument resolutionresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));resolvers.add(new RequestParamMapMethodArgumentResolver());resolvers.add(new PathVariableMethodArgumentResolver());resolvers.add(new PathVariableMapMethodArgumentResolver());resolvers.add(new MatrixVariableMethodArgumentResolver());resolvers.add(new MatrixVariableMapMethodArgumentResolver());resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new SessionAttributeMethodArgumentResolver());resolvers.add(new RequestAttributeMethodArgumentResolver());// Type-based argument resolutionresolvers.add(new ServletRequestMethodArgumentResolver());resolvers.add(new ServletResponseMethodArgumentResolver());// Custom argumentsif (getCustomArgumentResolvers() != null) {resolvers.addAll(getCustomArgumentResolvers());}// Catch-allresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));return resolvers;}/*** Return the list of return value handlers to use including built-in and* custom handlers provided via {@link #setReturnValueHandlers}.*/private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();// Single-purpose return value typeshandlers.add(new ModelAndViewMethodReturnValueHandler());handlers.add(new ModelMethodProcessor());handlers.add(new ViewMethodReturnValueHandler());handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));handlers.add(new StreamingResponseBodyReturnValueHandler());handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));handlers.add(new HttpHeadersReturnValueHandler());handlers.add(new CallableMethodReturnValueHandler());handlers.add(new DeferredResultMethodReturnValueHandler());handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));// Annotation-based return value typeshandlers.add(new ModelAttributeMethodProcessor(false));handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));// Multi-purpose return value typeshandlers.add(new ViewNameMethodReturnValueHandler());handlers.add(new MapMethodProcessor());// Custom return value typesif (getCustomReturnValueHandlers() != null) {handlers.addAll(getCustomReturnValueHandlers());}// Catch-allif (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));}else {handlers.add(new ModelAttributeMethodProcessor(true));}return handlers;}```
## RequestMappingHandlerMapping 
afterPropertiesSet -> initHandlerMethods 负责注册handelMappering
http://www.lryc.cn/news/2416824.html

相关文章:

  • python爬取discuz_爬虫技术实践(二)Discuz! 按板块爬取帖子内容实战
  • 一文看懂第三代E/E架构。
  • The world 浏览器 ,windows中的快捷操作
  • Response.Cookies和Request.Cookies的Cookies
  • 2014 360校园招聘技术类笔试题
  • 【Ubuntu安装QQ】
  • MikroTik RouterOS 5.x使用HunterTik 2.3.1进行破解
  • Android学习路线指南
  • 软件开发中的热更新概述
  • Doctype是什么与浏览器模式详解(标准模式混杂模式)
  • window安全小知识1——autorun.inf相关知识
  • VC++编程技巧83例
  • 【操作系统】知识梳理(六)输入输出系统
  • printf大部分参数详解
  • symfony快速构建restfull api--api-platform初体验(快速上手笔记)
  • 清除电脑各种使用记录不留痕迹,保护你的隐私!
  • jquery插件treeTable
  • 在Node.js版本v12.16.2中,`crypto`模块提供了加密功能的实现接口
  • 免费获取天气预报代码
  • 叉乘证明贝祖定理_谈方琳定理
  • oracle中exist什么意思,oracle中not exists 是什么意思 , oracle数据库中exists的作用
  • Nagios 安装教程
  • HS6621低功耗调试(HS6621CG)
  • QQ如何设置使用代理服务器?
  • 提权进阶篇
  • [从零学习汇编语言] - 计算机中的硬件与软件
  • 【爬虫】批量下载B站收藏夹视频 - Python
  • 动态IP?静态IP?看完本文你就懂了
  • 系统提示uxtheme.dll文件缺少出现错误问题
  • xvid编解码器安装