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. • 2014೥ʹ1.0͕ొ৔ • ελϯυΞϩϯͷSpringΞϓϦέʔγϣϯΛ࡞੒Ͱ͖Δ • ֤छߏ੒Λߦ͏ελʔλʔΛఏڙʢWebɺόονɺϝʔϧɺϩάɺDBͳͲʣ • AutoConfigurationʹΑΔαʔυύʔςΟ΋ؚΊͨࣗಈతͳઃఆ • Spring

    Initializer͸ݱࡏ͸Spring BootΛલఏʹ͍ͯ͠Δ • https://start.spring.io/ Spring Boot 11 https://spring.io/projects/spring-boot
  4. • 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
  5. 16 Spring BootΞϓϦέʔγϣϯͷdependenciesΛ௥͏ • ϓϩδΣΫτͷπϦʔԼ෦ͷʮ֎෦ϥΠϒϥϦʯ ͔Β֤dependenciesͷৄࡉΛݟΒΕΔɻେମ sources.jar΋෇͍͍ͯΔͷͰ࣮૷Λ௥͍͔͚ΒΕ Δɻ • શମΛோΊΔͱ͖͸Spring

    Framework, BootΛ௚ ઀։͘ͷ͕ศར • ಛఆͷॲཧΛ௥͍͔͚Δͱ͖͸ΞϓϦέʔγϣϯ ͔ΒϒϨʔΫϙΠϯτுͬͯsources.jar಺Λ௥͍ ͔͚Δͷ͕ศར
  6. 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/
  7. 21

  8. 22

  9. @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
  10. ༨ஊ: ಉ͡ΞϊςʔγϣϯΛ͚ͭͨΒಈ͘ 25 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = [ComponentScan.Filter( type

    = FilterType.CUSTOM, classes = [TypeExcludeFilter::class] ), ComponentScan.Filter(type = FilterType.CUSTOM, classes = [AutoConfigurationExcludeFilter::class])] ) class ServersideKotlinApplication
  11. 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ͷதͰߦ͍ͬͯΔɻ
  12. @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
  13. 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ͰΠϯελϯεΛ࡞Δ
  14. ίϯτϩʔϥͷؔ਺ͱύεΛͲ͔͜ͰϚοϐϯά͍ͯ͠Δ͸ͣ 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
  15. • ࣗಈతͳߏ੒Λఏڙ͢ΔͷͰجຊతʹ ΞϓϦέʔγϣϯىಈ࣌ʹॲཧ͕૸Δ • ؔ܎ͦ͠͏ͳAuto ConfigurationΛؤ ுͬͯ୳ͯ͠ϒϨʔΫϙΠϯτΛுΔ ͜ͱʹͳΔ ىಈ࣌͸Bootɺ࣮ߦ࣌͸Spring͔ϥΠϒϥϦ 31

    • ΞϓϦέʔγϣϯىಈޙ͸جຊతʹ Spring͔ϥΠϒϥϦͷಈ࡞ • ϒϨʔΫϙΠϯτΛுΕ͹େମ௥͍͔ ͚ΒΕΔ • AOP͸ಈతͳͷͰͪΐͬͱ΍΍͍͜͠ 4QSJOH#PPU
  16. 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ͱ͍͏໊લͰ೗Կʹ΋ո͍͠
  17. 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ͷॳظԽ͕͢΂ͯऴΘͬͨ͋ͱʹݺͼग़͞ΕΔؔ਺
  18. 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
  19. suspendʹͯ͠ΈΔ 43 @RestController class HelloController { @GetMapping("/") suspend fun index():

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

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