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

プロになるためのSpring上級知識 #jsug / advanced-spring-for-professionals

Masatoshi Tada
December 02, 2021

プロになるためのSpring上級知識 #jsug / advanced-spring-for-professionals

動画はこちら→ https://www.youtube.com/watch?v=c5ha8FmdNmw

Spring Fest 2021の資料です。

DIコンテナなどSpringの基礎知識が既にある方を対象に、上級者へステップアップするために必要な発展的知識を解説します。
このセッションを聞けば、プロジェクトをリードできるエンジニアになれること間違いなし!かも!?
・DIコンテナの要点復習
・同じ型のBeanが複数あるとどうなる?
・Java Configクラスを分割・統合するには?
・環境によって設定値やBeanを変更するには?
・Beanはどうやって作られる?

Masatoshi Tada

December 02, 2021
Tweet

More Decks by Masatoshi Tada

Other Decks in Technology

Transcript

  1. ͜ͷηογϣϯʹ͍ͭͯ ▸ 4QSJOH্ڃऀʹඞਢͱͳΔɺ%*ίϯςφؔ࿈ͷ 
 ൃలతͳ஌ࣝʹ͍ͭͯղઆ͠·͢ ▸ ͜ͷηογϣϯ͸ʲதڃऀ޲͚ʳͰ͢ ▸ 4QSJOHͷ%*ίϯςφͳͲʹ͍ͭͯ͸ɺ 


    ͋Δఔ౓஌͍ͬͯΔ͜ͱΛલఏʹղઆ͠·͢ ▸ 4QSJOH#PPUΛར༻͍ͯ͠ͳ͍͜ͱΛલఏͱ͠·͢ ▸ ར༻࣌ͷҧ͍͸ඞཁʹԠͯ͡ղઆ͠·͢ 2
  2. ࣗݾ঺հ 4 ▸ ଟాਅහ !TVLF@NBTB  ▸ ΫϨδοτΧʔυؔ࿈ͷ 
 γεςϜΛ࡞ͬͯΔ

    
 +BWBΤϯδχΞ ▸ ݩɾݚमτϨʔφʔ ▸ +46(ελοϑ
  3. 4QSJOH͸ίϯςφΛ͍࣋ͬͯΔ ▸ ίϯςφʹΠϯελϯεͷೖΕ෺ ▸ #FBOʹίϯςφͰ؅ཧ͞ΕͨΠϯελϯε 7 ίϯςφ #FBO #FBO #FBO

    #FBO #FBO ˞ʮΠϯελϯεʯͱ͸ɺ 
 ɹ΋ͪΖΜ+BWBͷΠϯελϯεͷ 
 ɹ͜ͱͰ͢ ඞཁʹԠͯ͡ 
 औΓग़ͯ͠࢖͏
  4. #FBOఆٛํ๏ᶃίϯϙʔωϯτεΩϟϯ ▸ ӈهͷΞϊςʔγϣϯΛ 
 Ϋϥεʹ෇͚Δͱɺ 
 @ComponentΛ෇͚ͨ 
 ͜ͱͱಉ͡ʹͳΔ ▸

    Ϋϥεͷ໾ׂʹԠͯ͡ 
 ม͑Δ 10 @Repository @Service @Controller @RestController @Configuration @ControllerAdvice @RestControllerAdvice ɾɾɾ ˞͜ΕΒͷΞϊςʔγϣϯͷιʔείʔυΛಡΉͱɺ 
 ɹ@Component͕෇͍͍ͯΔ͜ͱ͕෼͔Γ·͢ +BWB$PO fi H΋ #FBOʂ
  5. #FBOఆٛํ๏ᶃίϯϙʔωϯτεΩϟϯ ▸ #FBOͱ͍ͨ͠Ϋϥε 11 package com.example; @Component public class Hoge

    { ... } @Configuration @ComponentScan(basePackages = "com.example") public class AppConfig {} ▸ ઃఆΫϥε +BWB$PO fi H @Component͕ 
 ෇͍ͨΫϥεΛ 
 ୳͢ύοέʔδ
  6. #FBOఆٛํ๏ᶄ+BWB$PO fi H ▸ +BWB$PO fi HΫϥεʹϝιουΛ࡞੒͠ɺ 
 @BeanΛ෇Ճ͢Δ 


    ˠϝιουͷ໭Γ஋͕#FBOʹͳΔ 12 !$PNQPOFOU4DBO͸ෆཁ @Configuration public class AppConfig { @Bean public Hoge hoge() { return new Hoge(); } } !$PNQPOFOU͸ෆཁ public class Hoge { ... }
  7. #FBO*%ͱ͸ 14 @Component public class FooBar { ... } @Component("foo_bar")

    public class FooBar { ... } @Configuration public class FooConfig { @Bean public FooBar fooBar() { ... } @Bean(name = "foo_bar") public FooBar fooBar2() { ... } } fooBar foo_bar fooBar foo_bar #FBO*%
  8. ίϯςφΛ࡞Δɾ#FBOΛऔಘ͢Δ ▸ +BWB$PO fi HΫϥεΛࢦఆͯ͠ 
 ApplicationContext ίϯςφ Λ࡞੒ ▸

    ίϯϙʔωϯτεΩϟϯɾ+BWB$PO fi HͲͪΒͰ΋ڞ௨ ▸ getBean()Ͱ#FBOΛऔಘͰ͖Δ 15 ίϯςφͷ࡞੒ ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); #FBOΛ%*ίϯςφ͔ΒऔಘʢҾ਺͸ཉ͍͠#FBOͷσʔλܕʣ Hoge hoge = context.getBean(Hoge.class);
  9. %* ▸ ίϯετϥΫλʹ@AutowiredΛ෇Ճ͠ɺ 
 Ҿ਺ʹཉ͍͠#FBOΛࢦఆ ▸ ίϯςφ͕ద੾ͳ#FBOΛҾ਺ʹ୅ೖͯ͘͠ΕΔ ▸ Ϋϥε಺ʹίϯετϥΫλ͕ͭͷ৔߹ɺ@Autowired͸লུՄ 17

    @Component public class Hoge { private final Fuga fuga; @Autowired public Hoge(Fuga fuga) { this.fuga = fuga; } } ίϯςφ Hoge Fuga %* %*
  10. ͍ΖΜͳ%* ▸ ίϯετϥΫλΠϯδΣΫγϣϯ 18 @Component public class Hoge { private

    final Fuga fuga; @Autowired public Hoge(Fuga fuga) { this.fuga = fuga; } } @Component public class Hoge { private Fuga fuga; @Autowired public setFuga(Fuga fuga) { this.fuga = fuga; } } @Component public class Hoge { @Autowired Fuga fuga; } །ҰHogeΛมߋෆೳʹ Ͱ͖ΔͷͰ ίϯετϥΫλ ΠϯδΣΫγϣϯਪ঑ ˞มߋෆೳ Πϛϡʔλϒϧ ʹϑΟʔϧυͷ஋Λॻ׵ෆՄೳ ▸ ϑΟʔϧυΠϯδΣΫγϣϯ ▸ ϝιουΠϯδΣΫγϣϯ
  11. ͜ͷষͷ·ͱΊ ▸ ίϯςφʹΠϯελϯε #FBO ͷೖΕ෺ ▸ ίϯϙʔωϯτεΩϟϯ ▸ @ComponentͰ#FBOʹ͢ΔΫϥεΛࢦఆ ▸

    @ComponentScanͰ୳͢ൣғΛࢦఆ ▸ +BWB$PO fi H ▸ @BeanΛ෇Ճͨ͠ϝιουͷ໭Γ஋͕#FBOʹͳΔ ▸ %* ▸ ίϯετϥΫλͳͲʹ@AutowiredΛ෇Ճ 19
  12. Ͳ͏ͳΔʁ 21 @Component public class FooImpl1 implements Foo { ...

    } @Component public class FooImpl2 implements Foo { ... } @Component public class Bar { public Bar(Foo foo) { ... } } ܕ'PPʹ߹க͢Δ#FBO͕ͭ ˠྫ֎ൃੜʂʂ
  13. ᶃ!2VBMJ fi FSΛར༻ 23 @Component // Bean ID͸"fooImpl1" public class

    FooImpl1 implements Foo { ... } @Component // Bean ID͸"fooImpl2" public class FooImpl2 implements Foo { ... } @Component public class Bar { private final Foo foo; public Bar(@Qualifier("fooImpl1") Foo foo) { ... } } %*͍ͨ͠#FBOͷ#FBO*%Λࢦఆ
  14. !2VBMJ fi FSͷ΋͏ͭͷ࢖͍ํ 24 @Retention(RUNTIME) @Target({METHOD, TYPE, PARAMETER, FIELD}) @Qualifier

    public @interface Foo1 { ... } @Retention(RUNTIME) @Target({METHOD, TYPE, PARAMETER, FIELD}) @Qualifier public @interface Foo2 { ... } ▸ @QualifierΛ෇Ճͨ͠ಠࣗΞϊςʔγϣϯΛ 
 ͭ࡞੒
  15. !2VBMJ fi FSͷ΋͏ͭͷ࢖͍ํ 25 @Component @Foo1 public class FooImpl1 implements

    Foo { ... } @Component @Foo2 public class FooImpl2 implements Foo { ... } @Component public class Bar { public Bar(@Foo1 Foo foo) { ... } } ▸ ಠࣗΞϊςʔγϣϯΛ#FBOఆٛՕॴɾ%*Օॴͷ ྆ํʹ෇Ճ FooImpl1͕%*͞ΕΔ
  16. ᶄ!1SJNBSZΛར༻ 27 @Component @Primary public class FooImpl1 implements Foo {

    ... } @Component public class FooImpl2 implements Foo { ... } @Component public class Bar { public Bar(Foo foo) { ... } } FooImpl1͕%*͞ΕΔ ʢFooImpl2Λ%*͍ͨ͠৔߹͸ 
 @QualifierΛར༻ʣ
  17. ᶅ%*͢ΔܕΛม͑Δ 29 @Component public class FooImpl1 implements Foo { ...

    } @Component public class FooImpl2 implements Foo { ... } @Component public class Bar { public Bar(FooImpl1 foo) { ... } } %*͍ͨ͠#FBOͷܕΛ໌ࣔ
  18. +BWB$PO fi Hͷ෼ׂ 33 ▸ ͭͷ+BWB$PO fi Hʹ͢΂ͯͷ#FBOఆٛΛॻ͘ͱ 
 Ϋϥε͕ංେԽ͢Δ

    
 ˠ+BWB$PO fi HΛ෼ׂ͢Δ ▸ ྫ͑͹ԼهͷΑ͏ʹ෼ׂ͢Δ ᶃ 4QSJOH.7$༻$PO fi H ᶄ ϏδωεϩδοΫʴτϥϯβΫγϣϯ༻$PO fi H ᶅ σʔλιʔεʴ03Ϛούʔ༻$PO fi H
  19. ᶃ!*NQPSUͰ·ͱΊΔ 35 @Import(Config2.class) @Configuration public class Config1 { ... }

    @Configuration public class Config2 { ... } ApplicationContext context = new AnnotationConfigApplicationContext(Config1.class); $PO fi Hʹ$PO fi HΛ߹ମ $PO fi HͷΈΛࢦఆ
  20. ᶄίϯϙʔωϯτεΩϟϯ഑Լʹஔ͘ 37 @Configuration @ComponentScan(basePackages = "com.example") public class Config1 {

    ... } package com.example.foo; @Configuration public class Config2 { ... } εΩϟϯ഑Լʹஔ͚͹ ͦͷ+BWB$PO fi H͸࢖ΘΕΔ ApplicationContext context = new AnnotationConfigApplicationContext(Config1.class); $PO fi HͷΈΛࢦఆ
  21. ᶅ"QQMJDBUJPO$POUFYUͷίϯετϥΫλʹ 
 ɹ͢΂ͯࢦఆ͢Δ 38 ApplicationContext context = new AnnotationConfigApplicationContext( Config1.class,

    Config2.class); @Configuration public class Config1 { ... } @Configuration public class Config2 { ... } Մม௕Ҿ਺Ͱશ+BWB$PO fi HΛࢦఆ
  22. ࢖͍ॴ ▸ ݸਓతʹ͸΄ͱΜͲ 
 ʮᶄίϯϙʔωϯτεΩϟϯʯͰࡁ·ͤΔ ▸ ಛʹ4QSJOH#PPUͷ৔߹ ▸ ಛఆͷ+BWB$PO fi

    H͚ͩΛ࢖͍͍ͨ৔߹͸ɺ 
 ίϯϙʔωϯτεΩϟϯ֎ʹ࡞ͬͯ 
 ʮᶃ@ImportʯΛ࢖͏ 39
  23. ͜ͷষͷ·ͱΊ ▸ +BWB$PO fi H͸ద੾ʹ෼ׂ͢Δ ▸ ෼ׂͨ͠+BWB$PO fi HΛ·ͱΊΔํ๏͸ ᶃ

    @Import ᶄ ίϯϙʔωϯτεΩϟϯ ᶅ ApplicationContextͷҾ਺ ▸ ΄΅ᶄίϯϙʔωϯτεΩϟϯͰࡁ·ͤͯ0, 40
  24. ؀ڥʹΑͬͯ#FBOΛ੾Γସ͍͑ͨʂ ▸ ྫɿDataSourceΛςετ؀ڥͱຊ൪؀ڥͰ੾ସ 42 @Configuration public class AppConfig { @Bean

    public DataSource testDataSource() { return ૊ΈࠐΈσʔλϕʔε; } @Bean public DataSource productionDataSource() { return APαʔόʔ͔Βऔಘͨ͠σʔλιʔε; } } ͜ͷ··ͩͱDataSourceͷ %*࣌ʹ࣮ߦ࣌ྫ֎ ͜ͷ··ͩͱDataSourceͷ %*࣌ʹ࣮ߦ࣌ྫ֎
  25. ϓϩϑΝΠϧΛ࢖͏ 44 @Configuration public class AppConfig { @Bean @Profile("test") public

    DataSource testDataSource() { ... } @Bean @Profile("production") public DataSource productionDataSource() { ... } } $ export SPRING_PROFILES_ACTIVE=test $ mvn compile exec:java -DmainClass=com.example.Main testDataSourceͷΈ ༗ޮԽ͞ΕΔ
  26. ϓϩϑΝΠϧΛ࢖͏ 45 @Configuration @Profile("test") public class TestConfig { @Bean public

    DataSource testDataSource() { ... } } @Configuration @Profile("production") public class ProductionConfig { @Bean public DataSource productionDataSource() { ... } } ▸ +BWB$PO fi Hʹ΋@ProfileΛ෇ՃͰ͖Δ ࣮ߦ࣌ʹUFTUϓϩϑΝΠϧ ࢦఆͰ༗ޮԽ͞ΕΔ ࣮ߦ࣌ʹQSPEVDUJPOϓϩϑΝΠϧ ࢦఆͰ༗ޮԽ͞ΕΔ
  27. ओͳ࣮ߦ࣌ϓϩϑΝΠϧࢦఆํ๏ ᶃ +6OJUςετ ▸ @ActiveProfiles("test") ᶄ +7.γεςϜϓϩύςΟ ▸ java -Dspring.profiles.active=test

    ... ᶅ ؀ڥม਺ ▸ export SPRING_PROFILES_ACTIVE=test 46 ௿ ߴ ༏ઌॱҐ ※શͯͷํ๏Ͱෳ਺ͷϓϩϑΝΠϧ໊ΛࢦఆՄೳʢΧϯϚ۠੾Γʣ ଟ༻͢ΔͱNWOUFTUͰͷ 
 ςετ࣮ߦ͕࣌ؒ௕͘ͳΔͷͰ஫ҙ 
 %*ίϯςφ͕࠶࡞੒͞ΕΔͨΊ
  28. ϓϩϑΝΠϧͷ஫ҙ఺ ▸ ϓϩϑΝΠϧʹଐ͍ͯ͠ͳ͍#FBO͸ 
 ࣮ߦ࣌ʹͲͷϓϩϑΝΠϧΛࢦఆͯ͠΋ 
 ༗ޮԽ͞ΕΔ 47 @Configuration public

    class AppConfig { @Bean public Sample sample() { ... } @Bean @Profile("test") public Sample testSample() { ... } } ͜ͷ#FBO͸ͲΜͳϓϩϑΝΠϧΛ ࢦఆͯ͠΋࢖ΘΕΔ ͜ͷ#FBO͸UFTUϓϩϑΝΠϧ 
 ࢦఆ࣌ͷΈ࢖ΘΕΔ
  29. ϓϩύςΟϑΝΠϧ͔Βઃఆ஋Λऔಘ 48 @Configuration @PropertySource("classpath:/sample.properties") public class AppConfig { ... }

    # src/main/resources/sample.properties sample.message=Hello! @Component public class Sample { public Sample( @Value("${sample.message}") String message) { ... } } \ϓϩύςΟ໊^Ͱऔಘ ͜ͷ৔߹ɺΫϥεύε্ͷઈରύε fi MF΍IUUQ΋ར༻Մೳ
  30. ϓϩϑΝΠϧͰϓϩύςΟϑΝΠϧΛ੾Γସ͑Δ 50 @Configuration @PropertySource( "classpath:/sample-${SPRING_PROFILES_ACTIVE}.properties" ) public class AppConfig {

    ... } # src/main/resources/sample-test.properties sample.message=Hello Test! # src/main/resources/sample-production.properties sample.message=Hello Production! $ export SPRING_PROFILES_ACTIVE=test $ mvn compile exec:java -DmainClass=com.example.Main Hello Test! ϑΝΠϧ໊ʹϓϨʔεϗϧμʔΛؚΊΔ 4QSJOH#PPUͰ͸ඞཁͷແ͍ςΫχοΫ ޙड़
  31. 4QSJOH#PPUͷ৔߹ ▸ ઃఆ஋͸͢΂ͯBQQMJDBUJPOQSPQFSUJFTʹॻ͘ ▸ ಛఆͷϓϩϑΝΠϧͰͷΈར༻͢Δઃఆ஋͸ 
 BQQMJDBUJPOϓϩϑΝΠϧ໊QSPQFSUJFTʹॻ͘ ▸ ྫɿBQQMJDBUJPOUFTUQSPQFSUJFT 


    ɹɹBQQMJDBUJPOQSPEVDUJPOQSPQFSUJFT ▸ BQQMJDBUJPOQSPQFSUJFTͷ஋͸ɺ 
 ϓϩϑΝΠϧࢦఆͷ༗ແʹؔΘΒͣඞͣ࢖ΘΕΔ ▸ BQQMJDBUJPOQSPQFSUJFTͱ 
 BQQMJDBUJPOϓϩϑΝΠϧ໊QSPQFSUJFTʹಉ໊ͷઃఆ͕͋ͬͨΒɺ 
 ޙऀͷ΋ͷ͕࢖ΘΕΔ 51 @PropertySource 
 ෆཁ
  32. ͜ͷষͷ·ͱΊ ▸ @ProfileͰ#FBOΛάϧʔϓԽͰ͖Δ ▸ ࣮ߦ࣌ϓϩϑΝΠϧ໊ͷࢦఆํ๏͸͍Ζ͍Ζ ▸ @ActiveProfilesɺ-Dspring.profiles.activeɺ 
 ؀ڥม਺SPRING_PROFILES_ACTIVE ▸

    ϓϩύςΟϑΝΠϧ͸@PropertySourceͰࢦఆ ▸ ϑΝΠϧ໊ʹϓϨʔεϗϧμʔΛࢦఆ͢Δ͜ͱͰ؀ڥͰͷ੾ସՄೳ ▸ 4QSJOH#PPUͰ͸BQQMJDBUJPOQSPQFSUJFTʹઃఆΛॻ͘ ▸ 3FMBYFE#JOEJOH΍ઃఆͷ༏ઌॱҐ͸͓֮͑ͯ͘ 54
  33. ᶃ#FBOҰཡදΛ࡞Δ 57 Ϋϥε໊ ID είʔϓ ஗Ԇ ґଘઌID com.Foo foo singleton

    false (ͳ͠) com.Bar bar prototype true foo ɾɾɾ ɾɾɾ ɾɾɾ ɾɾɾ ɾɾɾ ※͜ͷද͸ΠϝʔδͰ͢ɻਖ਼֬ͳ΋ͷͰ͸͋Γ·ͤΜɻ ▸ 👇ͷΑ͏ͳදΛ࡞Δ ▸ ࣮ମ͸ org.springframework.beans.factory.config.BeanDefinition
  34. ᶃ#FBOҰཡදΛ࡞Δ ▸ #FBOҰཡද࡞੒ޙɺBeanFactoryPostProcessor͕ දͷҰ෦Λແཧ΍Γॻ͖׵͑Δ ▸ ओͳྫ ▸ PropertySourcesPlaceholderConfigurer ▸ @Valueͷ෦෼ΛϓϩύςΟ͔ΒಡΜͩ΋ͷʹஔ͖׵͑Δ

    ▸ LazyInitializationBeanFactoryPostProcessor ▸ 4QSJOH#PPUͷػೳʢspring.main.lazy-initialization=trueʣ ▸ શ#FBOͷ<஗Ԇ>ΛUSVFʹ͢Δ 59 ΠϯλϑΣʔε ࣮૷Ϋϥε ࣮૷Ϋϥε
  35. ᶄ#FBOͷίϯετϥΫλΛ࣮ߦ͢Δ ▸ #FBOҰཡදʹج͍ͮͯɺ 
 ίϯετϥΫλͰΠϯελϯεΛੜ੒͢Δ ▸ ͜ͷࡍɺίϯετϥΫλΠϯδΣΫγϣϯ΋ߦΘΕΔ ▸ Πϯελϯεੜ੒͸ɺґଘؔ܎ʹج͍ͮͯ 


    ਖ਼͍͠ॱ൪Ͱ࣮ߦ͞ΕΔ ▸ ྫɿ"͕#ʹґଘ͢Δˠ#ΛઌʹΠϯελϯεੜ੒͢Δ ▸ ϑΟʔϧυΠϯδΣΫγϣϯͱ 
 ϝιουΠϯδΣΫγϣϯ͸ɺ·ͩߦΘΕͳ͍ʂ 60
  36. ᶅ#FBOʹޙॲཧΛߦ͏ ▸ BeanPostProcessor͕#FBOΠϯελϯεʹޙॲཧΛࢪ͢ ▸ ओͳྫ ▸ AutowiredAnnotationBeanPostProcessor ▸ ϑΟʔϧυΠϯδΣΫγϣϯͱϝιουΠϯδΣΫγϣϯΛߦ͏ ▸

    CommonAnnotationBeanPostProcessor ▸ @PostConstruct͕෇Ճ͞ΕͨϝιουΛ࣮ߦ͢Δ ▸ AbstractAutoProxyCreator ▸ "01ͷͨΊͷϓϩΩγΠϯελϯεΛ࡞੒͢Δ 61 ΠϯλϑΣʔε ࣮૷Ϋϥε ࣮૷Ϋϥε ࣮૷Ϋϥε
  37. ิ଍ ▸ BeanFactoryPostProcessorɾ 
 BeanPostProcessorΛࣗ࡞͢Δ͜ͱ͸ك ▸ ֶश໨తͳΒΞϦ ▸ ੜ੒ϓϩηεΛ஌͍ͬͯΕ͹ɺڽͬͨ͜ͱΛ 


    ͢ΔࡍͷτϥϒϧΛղܾͰ͖Δ͔΋ ▸ ྫɿ#FBOੜ੒ॲཧʹ͸"01Λ͔͚ΒΕͳ͍ 
 ɹɹʢ·ͩϓϩΩγ͕࡞ΒΕΔલ͔ͩΒʣ 62
  38. ͜ͷষͷ·ͱΊ ᶃ #FBOҰཡදΛ࡞Δ ▸ ҰཡදΛ࡞੒ޙɺBeanFactoryPostProcessor͕ҰཡදͷҰ෦Λ ॻ͖׵͑Δ ᶄ #FBOͷίϯετϥΫλΛ࣮ߦ͢Δ ▸ ίϯετϥΫλΠϯδΣΫγϣϯ΋ߦΘΕΔ

    ᶅ #FBOʹޙॲཧΛߦ͏ ▸ BeanPostProcessor͕ϑΟʔϧυΠϯδΣΫγϣϯɾϝιουΠϯ δΣΫγϣϯɾ@PostConstructͷ࣮ߦɾϓϩΩγͷ࡞੒ͳͲΛߦ͏ 63
  39. ࠷ޙͷ·ͱΊ ▸ ಉ͡ܕͷ#FBO͸@Qualifierɾ@Primaryɾ 
 αϒΫϥεܕͳͲͰ൑ผͰ͖Δ ▸ ෼ׂͨ͠+BWB$PO fi H͸@Import΍ 


    ίϯϙʔωϯτεΩϟϯͰ౷߹͢Δ ▸ ઃఆ஋΍#FBOΛ؀ڥ͝ͱʹ࢖͍෼͚Δʹ͸ 
 ϓϩϑΝΠϧΛར༻͢Δ ▸ #FBOͷੜ੒ϓϩηε͸ 
 ᶃҰཡද࡞੒ˠᶄίϯετϥΫλ࣮ߦˠᶅޙॲཧ 64