Upgrade to Pro — share decks privately, control downloads, hide ads and more …

これどうやって動いてるんだ? Spring Framework/Bootのソースを読む

yagi
February 10, 2022
1.2k

これどうやって動いてるんだ? Spring Framework/Bootのソースを読む

yagi

February 10, 2022
Tweet

Transcript

  1. © Ubie, Inc. ҩྍػؔ޲͚ 4 Our Services AI ࣬ױ༧ଌ Τϯδϯ

    OCR ҩྍ৘ใ ςΩετԽ ݕࠪ αδΣετ ॲํༀ ݕࡧ Χϧς ੜ੒ ॳ਍ ໰਍ ࠶਍ ໰਍ ిࢠΧϧς ࿈ܞ Ӄ಺ γεςϜ ࿈ܞ ஍Ҭҩྍ ࿈ܞ ܦӦ؅ཧ ॲํ αδΣετ ॲํ ࿈ܞ ٹٸҩྍ αϙʔτ ೖӃ αϙʔτ ঱ঢ় νΣοΧʔ ҩྍػؔ Λ୳͢ ҩྍػؔ ࿈ܞ ҩྍػؔ ࣄલ໰਍ ద੾ͳ ਍ྍՊ Ҋ಺ ঱ঢ় ܦա؍࡯ ड਍ ༧໿ ड਍ αϙʔτ ϝσΟΞ ݈߁ཤྺ Ұݩ؅ཧ ҩྍػؔ޲͚ CRM ࢢൢༀ ݕࡧ ප໊ ࣙॻ ࣬ױܒൃ ઐ໳ҩྍػؔ Ҋ಺ AI࣬ױ༧ଌΤϯδϯΛத৺ʹɺtoCɺtoB྆໘Ͱࠓޙ΋৽ͨͳϓϩμΫτΛಉ࣌ʹ࡞͍ͬͯ͘༧ఆͰ͢ ҰൠϢʔβ޲͚ https://recruit.ubie.life/engineer
  2. • 2004೥ʹਖ਼ࣜϦϦʔεɻJavaΞϓϦέʔγϣϯ༻ͷϑϨʔϜϫʔΫ • Inversion of control͕த৺తͳػೳ • AOPɺσʔλΞΫηεϑϨʔϜϫʔΫɺτϥϯβΫγϣϯɺMVCɺϦϞʔτΞΫη εɺόονͳͲͷϞδϡʔϧ͕͋Δ •

    2018೥9݄ Spring Framework 5.1 ͔Β Kotlin 1.1αϙʔτ • https://spring.pleiades.io/guides/tutorials/spring-boot-kotlin/ Spring Framework 10 https://en.wikipedia.org/wiki/Spring_Framework
  3. • Spring Framework • https://github.com/spring-projects/spring-framework • git clone --depth 1

    [email protected]:spring-projects/spring-framework.git • Spring Boot • https://github.com/spring-projects/spring-boot • git clone --depth 1 [email protected]:spring-projects/spring-boot.git Spring FrameworkͱBootͷιʔε͸Githubʹ͋Δ 13
  4. 16 Spring BootΞϓϦέʔγϣϯͷdependenciesΛ௥͏ • ϓϩδΣΫτͷπϦʔԼ෦ͷʮ֎෦ϥΠϒϥϦʯ ͔Β֤dependenciesͷৄࡉΛݟΒΕΔɻେମ sources.jar΋෇͍͍ͯΔͷͰ࣮૷Λ௥͍͔͚ΒΕ Δɻ • શମΛோΊΔͱ͖͸Spring

    Framework, BootΛ௚ ઀։͘ͷ͕ศར • ಛఆͷॲཧΛ௥͍͔͚Δͱ͖͸ΞϓϦέʔγϣϯ ͔ΒϒϨʔΫϙΠϯτுͬͯsources.jar಺Λ௥͍ ͔͚Δͷ͕ศར
  5. APIΛ࣮૷͢Δ 19 package com.example.controller @RestController class HelloController { @GetMapping("/") fun

    index(): String { return "Greetings from Spring Boot!" } } https://spring.io/guides/gs/spring-boot/
  6. 21

  7. 22

  8. @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type

    = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { SpringBootApplicationΞϊςʔγϣϯ 24 https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java ෳ਺ͷΞϊςʔγϣϯΛ߹੒͍ͯ͠Δ AutoConfigurationΛ༗ޮʹ͢Δ DIͷͨΊͷίϯϙʔωϯτͳͲΛεΩϟϯ͢Δઃఆ 4QSJOH#PPU
  9. ༨ஊ: ಉ͡ΞϊςʔγϣϯΛ͚ͭͨΒಈ͘ 25 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = [ComponentScan.Filter( type

    = FilterType.CUSTOM, classes = [TypeExcludeFilter::class] ), ComponentScan.Filter(type = FilterType.CUSTOM, classes = [AutoConfigurationExcludeFilter::class])] ) class ServersideKotlinApplication
  10. ConfigurationClassParserͰίϯϙʔωϯτΛεΩϟϯ͢Δ 26 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class );

    if (!componentScans.isEmpty()… https://github.com/spring-projects/spring-framework/blob/main/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java#L289 ͜ͷΞϊςʔγϣϯͷ෇͍ͨΫϥεͷύοέʔδ഑ԼΛ૞ࠪ͠ɺΠϯελϯεͷ ੜ੒΍ॳظԽॲཧΛߦ͏ɻSpringApplicationͷதͰߦ͍ͬͯΔɻ
  11. @RestController΋ComponentΞϊςʔγϣϯΛ߹੒͍ͯ͠Δ 27 @RestController class HelloController { @GetMapping("/") fun index(): String

    { return "Greetings from Spring Boot!" } } ίϯϙʔωϯτεΩϟϯͷର৅ʹͳΔ https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/bind/annotation/RestController.java
  12. DefaultListableBeanFactoryͰΠϯελϯεΛ࡞Δ 28 for (String beanName : beanNames) { RootBeanDefinition bd

    = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { // লུ } else { getBean(beanName); } } } https://github.com/spring-projects/spring-framework/blob/main/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java#L908 ίϯϙʔωϯτεΩϟϯͰूΊͨ৘ใΛ࢖ͬͯDefaultListableBeanFactoryͰΠϯελϯεΛ࡞Δ
  13. ίϯτϩʔϥͷؔ਺ͱύεΛͲ͔͜ͰϚοϐϯά͍ͯ͠Δ͸ͣ 30 @RestController class HelloController { @GetMapping("/") fun index(): String

    { return "Greetings from Spring Boot!" } } HelloController$index -> GET [/] https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/bind/annotation/GetMapping.java#L46
  14. • ࣗಈతͳߏ੒Λఏڙ͢ΔͷͰجຊతʹ ΞϓϦέʔγϣϯىಈ࣌ʹॲཧ͕૸Δ • ؔ܎ͦ͠͏ͳAuto ConfigurationΛؤ ுͬͯ୳ͯ͠ϒϨʔΫϙΠϯτΛுΔ ͜ͱʹͳΔ ىಈ࣌͸Bootɺ࣮ߦ࣌͸Spring͔ϥΠϒϥϦ 31

    • ΞϓϦέʔγϣϯىಈޙ͸جຊతʹ Spring͔ϥΠϒϥϦͷಈ࡞ • ϒϨʔΫϙΠϯτΛுΕ͹େମ௥͍͔ ͚ΒΕΔ • AOP͸ಈతͳͷͰͪΐͬͱ΍΍͍͜͠ 4QSJOH#PPU
  15. WebMvcAutoConfigurationͰո͍͠BeanΛ୳͢ 33 4QSJOH#PPU @Bean @Primary @Override public RequestMappingHandlerMapping requestMappingHandlerMapping( @Qualifier("mvcContentNegotiationManager")

    ContentNegotiationManager contentNegotiationManager, @Qualifier("mvcConversionService") FormattingConversionService conversionService, @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { // Must be @Primary for MvcUriComponentsBuilder to work return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider); } https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java#L439 • GetMapping͸RequestMappingΛ߹੒͍ͯ͠ΔΞϊςʔγϣϯ • RequestMappingHandlerMappingͱ͍͏໊લͰ೗Կʹ΋ո͍͠
  16. RequestMappingHandlerMappingͰϦΫΤετύεͱؔ਺Λඥ͚͍ͭͯΔ 35 https://github.com/spring-projects/spring-framework/blob/main/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java#L205 public void afterPropertiesSet() { this.config = new

    RequestMappingInfo.BuilderConfiguration(); this.config.setTrailingSlashMatch(useTrailingSlashMatch()); this.config.setContentNegotiationManager(getContentNegotiationManager()); // ུ super.afterPropertiesSet(); } BeanͷॳظԽ͕͢΂ͯऴΘͬͨ͋ͱʹݺͼग़͞ΕΔؔ਺
  17. AbstractHandlerMethodMapping<T> (RequestMappingHandlerMappͷεʔύʔΫϥε) 37 protected void detectHandlerMethods(Object handler) { Class<?> handlerType

    = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { Class<?> userType = ClassUtils.getUserClass(handlerType); Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { try { return getMappingForMethod(method, userType); // ུ } https://github.com/spring-projects/spring-framework/blob/a0c97e4c36e5e07bc13bab4409ec740332a57871/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java#L275
  18. suspendʹͯ͠ΈΔ 43 @RestController class HelloController { @GetMapping("/") suspend fun index():

    String { return "Greetings from Spring Boot! $coroutineContext" } }
  19. • Spring Framework/Bootͷιʔε͸Githubʹ͋ΔɻIntelliJͰ։͚Δ • Spring Framework͕ίϯϙʔωϯτεΩϟϯͰΠϯελϯεΛ࡞ͬͨΓॳظԽͨ͠ΓDI͍ͯͯ͠ɺىಈϓϩηεΛ ಡΜͰ͍͘ͱΘ͔Δ • Spring Boot͕ϞδϡʔϧͷॳظઃఆܥΛAuto

    ConfigurationʹΑͬͯߦ͍ͬͯΔɻউखʹಈ͖ग़͢ܥ͸େମAuto ConfigurationΛ୳ͤ͹ݟ͔ͭΔ • @RestController͕෇͍ͨΫϥε͸ίϯϙʔωϯτεΩϟϯͰΠϯελϯε͕࡞ΒΕɺ RequestMappingHandlerMappingʹΑͬͯؔ਺ͱύεͱϝιου͕ඥ෇͚ΒΕΔ • ϦΫΤετΛड͚ͯؔ਺Λݺͼग़͍ͯ͠Δͷ͸InvocableHandlerMethodɻϒϨʔΫϙΠϯτுΕ͹ಈ͔͠ͳ͕Β ௥͑Δ ·ͱΊ 47