SpringBoot自動組立原理

11436 ワード

きのうぶんせき
従来のSpringプロジェクトには、Redisを使用するなど、多くのプロファイルがあります.一般的には、対応する依存jarパッケージのほかにアプリケーションが必要です.xmlにはJedisConnectionFactory、JedisPoolConfig、RedisTemplateが配置されています.しかしSpringBootを使うとpomによるxmlのjarパッケージは、これらのクラスを自動的に生成し、IOCコンテナに注入します.
  • 従来のSpringプロジェクトでは
  • を構成する必要があります.
    
    
    
    
  • SpringBootを使用するとpomを除く.xmlは対応するjarパッケージを導入する以外、applicationだけでよい.properties構成に対応する属性値は
  • である.
    概要
    自動アセンブリのプロセス:
  • は、各種の注釈+継承により、自動アセンブリコアメソッドを含むクラス
  • を導入する.
  • SpringApplication.run(Application.class,args)実行時に自動アセンブリメソッド
  • を呼び出す
  • 自動組立方法はspring-boot-autoconfigureを読み取る.义齿factoriesプロファイル.プロファイルには自動アセンブリクラスのすべてのプロファイルクラスのクラス名
  • があります.
  • 対応機能のコンフィギュレーションクラスを生成します.これらの機能構成クラスが有効になるには、クラスパスにそのクラスがあるかどうかの依存クラス(つまりpom.xmlに対応機能があるjarパッケージが必要)
  • を探します.
  • コンフィギュレーションクラスでは、最後の機能クラスが生成されると判断し、コンフィギュレーションクラスにはデフォルト属性値クラスが注入され、機能クラスはデフォルト値を参照して付与することができる.機能クラスを生成するには、カスタムが優先され、カスタムがない場合に自動アセンブリクラスが使用されます.

  • 以上のように、1つのクラスを自動的に組み立てるには2つの条件を満たす必要があります.
  • spring.factoriesには、このクラスの構成クラス(1つの構成クラスがその機能をめぐる複数の依存クラスを作成できる)
  • があります.
  • pom.xmlには対応するjarパッケージ
  • が必要です
    自動アセンブリの結果:
  • は各種の判断と依存により最終的に業務に必要なクラスを生成しIOC容器に注入した
  • .
  • 自動アセンブリによって生成されたクラスは、いくつかのデフォルトの属性値
  • を与える.
    注記参照線図
    複合注記+@importは対応するクラスをロードし、プログラム起動方法で自動ロードクラスを間接的に呼び出す方法です.
    @SpringBootApplication-->@EnableAutoConfiguration-->@Import(E n a b l e AutoConfigurationImportSelector.class)-->extends AutoConfigurationImportSelector-->selectImports()-->getExcludeAutoConfigurationsProperty()注釈参照によりSpringApplication.run()メソッドの場合、selectImports()が呼び出され、最終的に自動アセンブリがロードされます
    private List getExcludeAutoConfigurationsProperty() {
                RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(this.environment, "spring.autoconfigure.");
        }
    

    Redis自動アセンブリの例
  • spring-boot-autoconfigure.jar/META-INF/spring.factoriesでは、redisの機能構成クラスRedisAutoConfigurationのフルネーム
  • を含む120以上のデフォルト機能構成クラスを取得します.
    org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
    
  • RedisAutoConfigurationコンフィギュレーションクラスが有効になる条件の1つは@ConditionalOnClass:JedisConnectionです.class, RedisOperations.class, Jedis.class、だからclasspathに行って対応するclassファイル
  • を探します
    @Configuration
    @ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
    @EnableConfigurationProperties(RedisProperties.class)
    public class RedisAutoConfiguration {
            @Bean
            @ConditionalOnMissingBean(RedisConnectionFactory.class)
            public JedisConnectionFactory redisConnectionFactory()
                    throws UnknownHostException {
                return applyProperties(createJedisConnectionFactory());
            }
    }
    
  • pom.xmlには対応するjarパッケージがあり、対応する依存class:JedisConnectionにマッチします.class, RedisOperations.class, Jedis.class
  •         
                org.springframework.boot
                spring-boot-starter-data-redis
            
    
  • 照合に成功すると、この機能構成クラスは有効になり、デフォルトの属性構成クラス@E n a b l e C o n f i gurationProperties(RedisProperties.class)
  • が注入されます.
    @ConfigurationProperties(prefix = "spring.redis")
    public class RedisProperties {
        private int database = 0;
        private String url;
        private String host = "localhost";
        private String password;
        private int port = 6379;
    
  • Redis機能構成では、条件に応じて最終的なJedisConnectionFactory、RedisTemplateが生成されます.条件はIOC環境で、ユーザー定義@ConditionalOnMissingBean(RedisConnectionFactory.class)、RedisTemplate
  • がありません.
    @Configuration
    @ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
    @EnableConfigurationProperties(RedisProperties.class)
    public class RedisAutoConfiguration {
            @Bean
            @ConditionalOnMissingBean(RedisConnectionFactory.class)
            public JedisConnectionFactory redisConnectionFactory()
                    throws UnknownHostException {
                return applyProperties(createJedisConnectionFactory());
            }
    
            @Bean
            @ConditionalOnMissingBean(name = "redisTemplate")
            public RedisTemplate redisTemplate(
                    RedisConnectionFactory redisConnectionFactory)
                            throws UnknownHostException {
                RedisTemplate template = new RedisTemplate();
                template.setConnectionFactory(redisConnectionFactory);
                return template;
            }
    }
    
  • 最終的に作成されたデフォルトのアセンブリクラスは、機能構成クラスの@Bean注釈を通じてIOCに
  • 注入されます.
    コア注記
    @SpringBootApplicationでは、SpringBootConfiguration、EnableAutoConfiguration、ComponentScanの3つの注記を統合しています.
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan
    public @interface SpringBootApplication {
    }
    
  • @SpringBootConfiguration:実際には@Configurationであり、このbeanがspringのxmlファイルであることを示すIOCコンテナの構成クラスであることを示しています.
  • @Configuration
    public class ShiroConfig {
        @Bean
        public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    }
    
  • @ComponentScan:Springで指定されたMVC環境スキャンパッケージとSpring IOCのスキャンパッケージを指定し、スキャンパスはそのクラスが存在するすべてのパッケージです.SpringBootの注記はすべての同じパスの下のクラスをスキャンし、@ControllerクラスはMVCクラスに帰位し、その他のクラスはSpringのクラス
  • である.
      mvc     
      
    
    Spring    Spring         
    
    
  • @EnableAutoConfiguration:Spring Boot自動構成機能をオンにすることを示し、Spring Bootはアプリケーションの依存、カスタムbean、classpathの下にクラスがあるかどうかなどの要因によって必要なbeanを推測し、IOCコンテナに登録します.
  • @AutoConfigurationPackage
    @Import(EnableAutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {}
    
  • @Conditional注記は、ある条件が満たされた後にbeanを初期化するか、ある構成を有効にするかを示します.条件クラスの作成をカスタマイズし、Conditionインタフェースを実現し、MyServiceクラスがJdbcTemplateConditionに依存するなど、そのmatches()メソッドを上書きする.クラスは条件クラスで、JdbcTemplateCondition.class調整クラスの条件は、classpathの下にJdbcTemplateというクラスをロードできることです.
  • @Conditional(JdbcTemplateCondition.class)
    @Service
    public MyService service() {
        ......
    }
    
    public class JdbcTemplateCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            try {
            conditionContext.getClassLoader().loadClass("org.springframework.jdbc.core.JdbcTemplate");
                return true;
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return false;
        }
    }
    
  • @ConditionalOnClass:classpathで対応するclassファイルが見つかった場合、この構成クラス、またはメソッドが有効になることを示します.例えばclasspathにはBillyがあります.class、この配置クラスは有効になります.つまり、FighterというBeanはIOC容器に
  • 注入されます.
    @Configuration
    @ConditionalOnClass({Billy.class})
    public class VanConfig {
        @Bean
        public Fighter billy(){
            return new Billy();
        }
    }
    
  • @ConditionalOnBean:IOC環境下でcontainsBeanがtrueの場合、通過することを示しています.例えば以下、classpathの下にTestが存在するも.だが...classはIOCに注入されず、誤報を出すこともあります.HelloService注入に失敗しました.
  •     @Bean
        @ConditionalOnBean(Test.class)
        public HelloService test(){
            return new HelloService();
        }
    
  • @ConditionalOnMissingBeanこれはすごい注釈で、デフォルトの構成を実現するときにカスタマイズを優先します.コンテキスト(IOC環境)に既にこのBeanがある場合は無視し、このBeanがない場合はデフォルトの自動アセンブリBeanに戻ります.たとえば、Animalインタフェースに依存するように適用し、手動でanimalを注入すると、注入されたbeanに準じ、注入されていない場合は@ConditionalOnMissingBeanによって検出され、デフォルトのAutoConfigAnimalをbeanとして使用します.
  • @RestController
    public class MyRun {
        @Autowired
        private Animal animal;
    
        @RequestMapping("/auto/home")
        public String home(){
            return animal.eat();
        }
    }
    
    @Component("animal")
    public class Human implements Animal{
        public String eat() {
            return "eat rice";
        }
    }
    
    @Configuration
    public class TestConfig {
        @Bean
        @ConditionalOnMissingBean(Animal.class)
        public Animal test(){
            return new AutoConfigAnimal();
        }
    }
    
    public class AutoConfigAnimal implements Animal{
        public String eat() {
            return "eat anything";
        }
    }
    

    依存注記(Redisの例)
  • @SpringBootApplication:sbプロジェクトアプリケーション起動クラスの注釈は、実は3つの注釈の組み合わせです:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan、自動アセンブリで2番目の
  • が機能します.
  • @EnableAutoConfiguration:SBアプリケーションが自動アセンブリを開始する機能(対応するBeanをIOCコンテナにロードし、デフォルトの構成に従って属性に値を付与することを含む)
  • を示す.
  • @Import(E n a b l e AutoConfigurationImportSelector.class):この注釈は比較的強く、IOCに登録されていないBeanをIOCに強制登録することができ、自動構成機能を起動するにはE n a b l e AutoConfigurationImportSelectorを導入する必要があることを示している.classは
  • です
  • @Configuration
  • @ConditionalOnClass({JedisConnection.class,RedisOperations.class,Jedis.class}):RedisAutoコンフィギュレーションクラスを機能させるには、これらのクラスを含むjarパッケージが必要であることを示す
  • @E n a b l e ConfigurationProperties(RedisProperties.class):RedisPropertiesがデフォルトで参照されていることを示します.class内の構成
  • @C o n d i tionalOnMissingBean(RedisConnectionFactory.class):ユーザーがRedisConnectionFactoryに注入をカスタマイズしていない場合を示します.クラスは、デフォルトのJedisConnectionFactory
  • を使用します.
    コードロジック:
    自動アセンブリプロセス
  • は種々の注釈によりクラスとクラスの依存関係を実現する、コンテナは起動時にApplication.run、E n a b l e A u t o C o n f i g u r ationImportSelectorが呼び出されます.classのselectImportsメソッド(実はその親のメソッド)
  • selectImportsメソッドは最終的にSpringFactoriesLoaderを呼び出す.loadFactoryNameメソッドを使用して、一般的なBeanConfigurationの包括的なリスト
  • を取得します.
  • loadFactoryNameメソッドFACTORIES_を読み込みます.RESOURCE_LOCATION(つまりspring-boot-autoconfigure.jarの下のspring.factories)は、すべてのSpring関連BeanのフルネームClassNameを取得し、約120個の
  • selectImportsメソッドはfilter(configurations,autoConfigurationMetadata)を呼び出し続ける.このとき、これらのBeanConfigurationの条件に基づいて、一つ一つフィルタリングします.最も重要なのは@ConditionalOnClassです.この条件注釈はclasspathの下で検索されます.jarパッケージにはこの条件依存クラスがあるかどうかです.だから、対応するjarパッケージが必要です.これらの依存クラスがあります.このとき、これらの機能構成クラスは
  • に有効になります.
  • 機能構成クラスが有効になると、依存するデフォルト属性値クラスが取得され、その機能のデフォルト属性値
  • がいくつかあります.
  • 機能構成クラスには最終的な機能Beanが配置されています.このとき@ConditionalOnMissingBeanでユーザーがカスタマイズしたかどうかを判断し、ユーザーがカスタマイズしていない場合はデフォルトの機能クラスを作成し、IOCに注入する
  • public static List loadFactoryNames(Class> factoryClass, ClassLoader classLoader) {
                Enumeration urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
                List result = new ArrayList();
                while (urls.hasMoreElements()) {
                    URL url = urls.nextElement();
                    Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                    String factoryClassNames = properties.getProperty(factoryClassName);
                    result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
                }
                return result;
        }
    

    spring.factoriesファイル:
    org.springframework.context.ApplicationContextInitializer=\
    org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
    org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
    

    ブログ参照
    https://www.jianshu.com/p/83693d3d0a65