springboot核心原理

原文出自点击打开连接html

 这篇来先经过学习分析Spring Boot的运行原理后,根据已掌握的知识来自定义一个start pom。java

      Spring Boot关于自动配置的源码在spring-boot-autoconfigure-xxx.jar内。若想查看有哪些自动配置,能够查看这里的源码。能够经过下面几种方式查看当前项目中已启用和未启用的自动配置的报告。react

     1)运行jar包时增长--debug参数:git

      java -jar xx.jar  --debuggithub

      2)在application中设置属性,debug=true:web

[plain]  view plain  copy
  1. spring:  
  2.   profiles:  
  3.     active: prod  
  4.   
  5.   
  6.   
  7. book:  
  8.   author: jack  
  9.   name: hello world  
  10.   
  11. author:  
  12.   name: jack  
  13.   age: 18  
  14.   
  15. debug: true  


      此时启动,能够在控制台输出。已启用的自动配置为:
redis

[plain]  view plain  copy
  1. Positive matches:  
  2. -----------------  
  3.   
  4.    DispatcherServletAutoConfiguration matched:  
  5.       - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)  
  6.       - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)  
  7.   
  8.    DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:  
  9.       - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)  
  10.       - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)  
  11.   
  12.    DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration matched:  
  13.       - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)  
  14.       - DispatcherServlet Registration did not find servlet registration bean (DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition)  
  15.   
  16.    DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration matched:  
  17.       - @ConditionalOnBean (names: dispatcherServlet; types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found beans 'dispatcherServlet', 'dispatcherServlet' (OnBeanCondition)  
  18.   
  19.    EmbeddedServletContainerAutoConfiguration matched:  
  20.       - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)  
  21.   
  22.    EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat matched:  
  23.       - @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.apache.catalina.startup.Tomcat'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)  
  24.       - @ConditionalOnMissingBean (types: org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; SearchStrategy: current) did not find any beans (OnBeanCondition)  


   未启用的自动配置为:spring

[plain]  view plain  copy
  1. Negative matches:  
  2. -----------------  
  3.   
  4.    ActiveMQAutoConfiguration:  
  5.       Did not match:  
  6.          - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)  
  7.   
  8.    AopAutoConfiguration:  
  9.       Did not match:  
  10.          - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)  
  11.   
  12.    ArtemisAutoConfiguration:  
  13.       Did not match:  
  14.          - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory' (OnClassCondition)  
  15.   
  16.    BatchAutoConfiguration:  
  17.       Did not match:  
  18.          - @ConditionalOnClass did not find required classes 'org.springframework.batch.core.launch.JobLauncher', 'org.springframework.jdbc.core.JdbcOperations' (OnClassCondition)  
  19.   
  20.    CacheAutoConfiguration:  
  21.       Did not match:  
  22.          - @ConditionalOnBean (types: org.springframework.cache.interceptor.CacheAspectSupport; SearchStrategy: all) did not find any beans (OnBeanCondition)  
  23.       Matched:  
  24.          - @ConditionalOnClass found required class 'org.springframework.cache.CacheManager'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)  
  25.   
  26.    CacheAutoConfiguration.CacheManagerJpaDependencyConfiguration:  
  27.       Did not match:  
  28.          - @ConditionalOnClass did not find required class 'org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean' (OnClassCondition)  
  29.          - Ancestor org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition)  
  30.   
  31.    CaffeineCacheConfiguration:  
  32.       Did not match:  
  33.          - @ConditionalOnClass did not find required classes 'com.github.benmanes.caffeine.cache.Caffeine', 'org.springframework.cache.caffeine.CaffeineCacheManager' (OnClassCondition)  
  34.   
  35.    CassandraAutoConfiguration:  
  36.       Did not match:  
  37.          - @ConditionalOnClass did not find required class 'com.datastax.driver.core.Cluster' (OnClassCondition)  
  38.   
  39.    CassandraDataAutoConfiguration:  
  40.       Did not match:  
  41.          - @ConditionalOnClass did not find required classes 'com.datastax.driver.core.Cluster', 'org.springframework.data.cassandra.core.CassandraAdminOperations' (OnClassCondition)  
  42.   
  43.    CassandraRepositoriesAutoConfiguration:  
  44.       Did not match:  
  45.          - @ConditionalOnClass did not find required classes 'com.datastax.driver.core.Session', 'org.springframework.data.cassandra.repository.CassandraRepository' (OnClassCondition)  
  46.   
  47.    CloudAutoConfiguration:  
  48.       Did not match:  
  49.          - @ConditionalOnClass did not find required class 'org.springframework.cloud.config.java.CloudScanConfiguration' (OnClassCondition)  
  50.   
  51.    CouchbaseAutoConfiguration:  
  52.       Did not match:  
  53.          - @ConditionalOnClass did not find required classes 'com.couchbase.client.java.CouchbaseBucket', 'com.couchbase.client.java.Cluster' (OnClassCondition)  
  54.   
  55.    CouchbaseCacheConfiguration:  
  56.       Did not match:  
  57.          - @ConditionalOnClass did not find required classes 'com.couchbase.client.java.Bucket', 'com.couchbase.client.spring.cache.CouchbaseCacheManager' (OnClassCondition)  
  58.   
  59.    CouchbaseDataAutoConfiguration:  
  60.       Did not match:  
  61.          - @ConditionalOnClass did not find required classes 'com.couchbase.client.java.Bucket', 'org.springframework.data.couchbase.repository.CouchbaseRepository' (OnClassCondition)  
  62.   
  63.    CouchbaseRepositoriesAutoConfiguration:  
  64.       Did not match:  
  65.          - @ConditionalOnClass did not find required classes 'com.couchbase.client.java.Bucket', 'org.springframework.data.couchbase.repository.CouchbaseRepository' (OnClassCondition)  
  66.   
  67.    DataSourceAutoConfiguration:  
  68.       Did not match:  
  69.          - @ConditionalOnClass did not find required class 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)  
  70.   
  71.    DataSourceTransactionManagerAutoConfiguration:  
  72.       Did not match:  
  73.          - @ConditionalOnClass did not find required classes 'org.springframework.jdbc.core.JdbcTemplate', 'org.springframework.transaction.PlatformTransactionManager' (OnClassCondition)  
  74.   
  75.    DeviceDelegatingViewResolverAutoConfiguration:  
  76.       Did not match:  
  77.          - @ConditionalOnClass did not find required class 'org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver' (OnClassCondition)  
  78.   
  79.    DeviceResolverAutoConfiguration:  
  80.       Did not match:  
  81.          - @ConditionalOnClass did not find required classes 'org.springframework.mobile.device.DeviceResolverHandlerInterceptor', 'org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver' (OnClassCondition)  
  82.   
  83.    DispatcherServletAutoConfiguration.DispatcherServletConfiguration#multipartResolver:  
  84.       Did not match:  
  85.          - @ConditionalOnBean (types: org.springframework.web.multipart.MultipartResolver; SearchStrategy: all) did not find any beans (OnBeanCondition)  
  86.   
  87.    EhCacheCacheConfiguration:  
  88.       Did not match:  
  89.          - @ConditionalOnClass did not find required classes 'net.sf.ehcache.Cache', 'org.springframework.cache.ehcache.EhCacheCacheManager' (OnClassCondition)  


一:运做原理
apache

       关于Spring Boot的运做原理,咱们仍是回归到@SpringBootApplication注解上来,这个注解是一个组合注解,它的核心功能是由@EnableAutoConfiguration注解提供的,下面看看@EnableAutoConfiguration的注解的源码以下:浏览器

[java]  view plain  copy
  1. //  
  2. // Source code recreated from a .class file by IntelliJ IDEA  
  3. // (powered by Fernflower decompiler)  
  4. //  
  5.   
  6. package org.springframework.boot.autoconfigure;  
  7.   
  8. import java.lang.annotation.Documented;  
  9. import java.lang.annotation.ElementType;  
  10. import java.lang.annotation.Inherited;  
  11. import java.lang.annotation.Retention;  
  12. import java.lang.annotation.RetentionPolicy;  
  13. import java.lang.annotation.Target;  
  14. import org.springframework.context.annotation.Import;  
  15.   
  16. @Target({ElementType.TYPE})  
  17. @Retention(RetentionPolicy.RUNTIME)  
  18. @Documented  
  19. @Inherited  
  20. @AutoConfigurationPackage  
  21. @Import({EnableAutoConfigurationImportSelector.class})  
  22. public @interface EnableAutoConfiguration {  
  23.     String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";  
  24.   
  25.     Class<?>[] exclude() default {};  
  26.   
  27.     String[] excludeName() default {};  
  28. }  


    这里关键功能是@Import注解导入的配置功能,

[java]  view plain  copy
  1. EnableAutoConfigurationImportSelector  

使用SpringFactoriesLoader.loadFactoryNames方法来扫描具备META-INF/spring.factories文件的jar包,spring-boot-autoconfigure-xxx.jar里就有一个spring.factories文件,此文件声明了有哪些自动配置,以下:

[plain]  view plain  copy
  1. # Initializers  
  2. org.springframework.context.ApplicationContextInitializer=\  
  3. org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\  
  4. org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer  
  5.   
  6. # Application Listeners  
  7. org.springframework.context.ApplicationListener=\  
  8. org.springframework.boot.autoconfigure.BackgroundPreinitializer  
  9.   
  10. # Auto Configuration Import Listeners  
  11. org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\  
  12. org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener  
  13.   
  14. # Auto Configuration Import Filters  
  15. org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\  
  16. org.springframework.boot.autoconfigure.condition.OnClassCondition  
  17.   
  18. # Auto Configure  
  19. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  
  20. org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\  
  21. org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\  
  22. org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\  
  23. org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\  
  24. org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\  
  25. org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\  
  26. org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\  
  27. org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\  
  28. org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\  
  29. org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\  
  30. org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\  
  31. org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\  
  32. org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\  
  33. org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\  
  34. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\  
  35. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\  
  36. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\  
  37. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\  
  38. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\  
  39. org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\  
  40. org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\  
  41. org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\  
  42. org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\  
  43. org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\  
  44. org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\  
  45. org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\  
  46. org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\  
  47. org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\  
  48. org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\  
  49. org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\  
  50. org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\  
  51. org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\  
  52. org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\  
  53. org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\  
  54. org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\  
  55. org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\  
  56. org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\  
  57. org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\  
  58. org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\  
  59. org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\  
  60. org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\  
  61. org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\  
  62. org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\  
  63. org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\  
  64. org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\  
  65. org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\  
  66. org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\  
  67. org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\  
  68. org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\  
  69. org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\  
  70. org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\  
  71. org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\  
  72. org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\  
  73. org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\  
  74. org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\  
  75. org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\  
  76. org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\  
  77. org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\  
  78. org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\  
  79. org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\  
  80. org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\  
  81. org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\  
  82. org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\  
  83. org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\  
  84. org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\  
  85. org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\  
  86. org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\  
  87. org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\  
  88. org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\  
  89. org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\  
  90. org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\  
  91. org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\  
  92. org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\  
  93. org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\  
  94. org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\  
  95. org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\  
  96. org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\  
  97. org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\  
  98. org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\  
  99. org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\  
  100. org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\  
  101. org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\  
  102. org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\  
  103. org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\  
  104. org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\  
  105. org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\  
  106. org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\  
  107. org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\  
  108. org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\  
  109. org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\  
  110. org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\  
  111. org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\  
  112. org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\  
  113. org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\  
  114. org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\  
  115. org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration  
  116.   
  117. # Failure analyzers  
  118. org.springframework.boot.diagnostics.FailureAnalyzer=\  
  119. org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\  
  120. org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\  
  121. org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer  
  122.   
  123. # Template availability providers  
  124. org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\  
  125. org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\  
  126. org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\  
  127. org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\  
  128. org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\  
  129. org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider  


二:核心注解

      打开上面任意一个AutoConfiguration文件,通常都有下面的条件注解,在spring-boot-autoconfigure-xxx.jar的org.springframework.boot.autocinfigure.condition包下,条件注解以下:

      @ConditionalOnBean:当容器里有指定的Bean的条件下

      @ConditionalOnClass:当类路径下有指定的类的条件下

      @ConditionalOnExpression:基于SpEL表达式做为判断条件

      @ConditionalOnJava:基于JVM版本做为判断条件

      @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置

      @@ConditionalOnMissingBean:当容器里没有指定Bean的状况下

     @ConditionalOnMissingClass:当类路径下没有指定的类的条件下

      @ConditionalOnNotWebApplication:当前项目不是Web项目的条件下

      @ConditionalOnProperty:指定的属性是否有指定的值

     @ConditionalOnResource:类路径是否有指定的值

      @ConditionalOnSingleCandidate:当指定bean在容器中只有一个,或者虽然有多个可是指定首先的Bean

      @ConditionalOnWebApplication:当前项目是Web项目的条件下

     这些注解都是组合了@Condition元注解,只是使用了不一样的条件(Condition),

     下面看看@ConditionalOnWebApplication的源代码:

[java]  view plain  copy
  1. //  
  2. // Source code recreated from a .class file by IntelliJ IDEA  
  3. // (powered by Fernflower decompiler)  
  4. //  
  5.   
  6. package org.springframework.boot.autoconfigure.condition;  
  7.   
  8. import java.lang.annotation.Documented;  
  9. import java.lang.annotation.ElementType;  
  10. import java.lang.annotation.Retention;  
  11. import java.lang.annotation.RetentionPolicy;  
  12. import java.lang.annotation.Target;  
  13. import org.springframework.context.annotation.Conditional;  
  14.   
  15. @Target({ElementType.TYPE, ElementType.METHOD})  
  16. @Retention(RetentionPolicy.RUNTIME)  
  17. @Documented  
  18. @Conditional({OnWebApplicationCondition.class})  
  19. public @interface ConditionalOnWebApplication {  
  20. }  

    从源代码能够看出,此注解使用的条件是OnWebApplicationCondition,下面看看这个条件是如何构造的:

[java]  view plain  copy
  1. //  
  2. // Source code recreated from a .class file by IntelliJ IDEA  
  3. // (powered by Fernflower decompiler)  
  4. //  
  5.   
  6. package org.springframework.boot.autoconfigure.condition;  
  7.   
  8. import org.springframework.boot.autoconfigure.condition.ConditionMessage.Builder;  
  9. import org.springframework.context.annotation.ConditionContext;  
  10. import org.springframework.core.annotation.Order;  
  11. import org.springframework.core.type.AnnotatedTypeMetadata;  
  12. import org.springframework.util.ClassUtils;  
  13. import org.springframework.util.ObjectUtils;  
  14. import org.springframework.web.context.WebApplicationContext;  
  15. import org.springframework.web.context.support.StandardServletEnvironment;  
  16.   
  17. @Order(-2147483628)  
  18. class OnWebApplicationCondition extends SpringBootCondition {  
  19.     private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context.support.GenericWebApplicationContext";  
  20.   
  21.     OnWebApplicationCondition() {  
  22.     }  
  23.   
  24.     public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {  
  25.         boolean required = metadata.isAnnotated(ConditionalOnWebApplication.class.getName());  
  26.         ConditionOutcome outcome = this.isWebApplication(context, metadata, required);  
  27.         if (required && !outcome.isMatch()) {  
  28.             return ConditionOutcome.noMatch(outcome.getConditionMessage());  
  29.         } else {  
  30.             return !required && outcome.isMatch() ? ConditionOutcome.noMatch(outcome.getConditionMessage()) : ConditionOutcome.match(outcome.getConditionMessage());  
  31.         }  
  32.     }  
  33.   
  34.     private ConditionOutcome isWebApplication(ConditionContext context, AnnotatedTypeMetadata metadata, boolean required) {  
  35.         Builder message = ConditionMessage.forCondition(ConditionalOnWebApplication.classnew Object[]{required ? "(required)" : ""});  
  36.         if (!ClassUtils.isPresent("org.springframework.web.context.support.GenericWebApplicationContext", context.getClassLoader())) {  
  37.             return ConditionOutcome.noMatch(message.didNotFind("web application classes").atAll());  
  38.         } else {  
  39.             if (context.getBeanFactory() != null) {  
  40.                 String[] scopes = context.getBeanFactory().getRegisteredScopeNames();  
  41.                 if (ObjectUtils.containsElement(scopes, "session")) {  
  42.                     return ConditionOutcome.match(message.foundExactly("'session' scope"));  
  43.                 }  
  44.             }  
  45.   
  46.             if (context.getEnvironment() instanceof StandardServletEnvironment) {  
  47.                 return ConditionOutcome.match(message.foundExactly("StandardServletEnvironment"));  
  48.             } else {  
  49.                 return context.getResourceLoader() instanceof WebApplicationContext ? ConditionOutcome.match(message.foundExactly("WebApplicationContext")) : ConditionOutcome.noMatch(message.because("not a web application"));  
  50.             }  
  51.         }  
  52.     }  
  53. }  


      从isWebApplication方法能够看出,判断条件是:

     1)GenericWebApplicationContext是否在类路径中

      2)容器里是否为session的scope

      3)当前容器的Enviroment是否为StandardServletEnvironment

      4)当前的ResourceLoader是否为WebApplicationContext

      5)咱们须要构造ConditionOutcome类的对象来帮助咱们,最终经过ConditionOutcome.isMatch方法返回布尔值来肯定条件


   

三:实战

   下面咱们本身来写一个starter pom,这意味着咱们不只有自动配的功能,并且具备更通用的藕合度更低的配置。为了方便理解,在这里将Bean的属性在application.yml中配置

    1,新建start的Maven项目,这里我为了管理,把这个项目做为module,如图所示:



修改pom.xml代码以下:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  5.     <parent>  
  6.         <artifactId>SpringCloudTwo</artifactId>  
  7.         <groupId>com.jack</groupId>  
  8.         <version>1.0-SNAPSHOT</version>  
  9.     </parent>  
  10.     <modelVersion>4.0.0</modelVersion>  
  11.   
  12.     <artifactId>com.jack.springboot-starter-hello</artifactId>  
  13.   
  14.     <properties>  
  15.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  16.     </properties>  
  17.   
  18.     <dependencies>  
  19.         <dependency>  
  20.             <groupId>org.springframework.boot</groupId>  
  21.             <artifactId>spring-boot-autoconfigure</artifactId>  
  22.             <version>1.5.6.RELEASE</version>  
  23.         </dependency>  
  24.     </dependencies>  
  25.   
  26. </project>  

     上面增长了Spring Boot自身的自动配置做为依赖。

  2,属性配置,代码以下:

[java]  view plain  copy
  1. package com.jack.springboot.starter.hello;  
  2.   
  3. import org.springframework.boot.context.properties.ConfigurationProperties;  
  4.   
  5. @ConfigurationProperties(prefix = "hello")  
  6. public class HelloServiceProperties {  
  7.     private static final String MSG = "world";  
  8.     private String msg = MSG;  
  9.   
  10.     public static String getMSG() {  
  11.         return MSG;  
  12.     }  
  13.   
  14.     public String getMsg() {  
  15.         return msg;  
  16.     }  
  17.   
  18.     public void setMsg(String msg) {  
  19.         this.msg = msg;  
  20.     }  
  21. }  


在application.yml中经过hello.msg来设置,若不设置,默认为hello.msg=world


3,判断依据类,代码以下:

[java]  view plain  copy
  1. package com.jack.springboot.starter.hello;  
  2.   
  3. public class HelloService {  
  4.     private String msg;  
  5.   
  6.     public String getMsg() {  
  7.         return msg;  
  8.     }  
  9.   
  10.     public void setMsg(String msg) {  
  11.         this.msg = msg;  
  12.     }  
  13.     public String sayHello(){  
  14.         return "Hello "+msg;  
  15.     }  
  16. }  


    下面根据此类的存在与否来建立这个类的Bean,这个类能够是第三方的类库

4,自动配置类,代码以下:

[java]  view plain  copy
  1. package com.jack.springboot.starter.hello;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;  
  5. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  
  6. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  
  7. import org.springframework.boot.context.properties.EnableConfigurationProperties;  
  8. import org.springframework.context.annotation.Bean;  
  9. import org.springframework.context.annotation.Configuration;  
  10.   
  11. @Configuration  
  12. @EnableConfigurationProperties(HelloServiceProperties.class)  
  13. @ConditionalOnClass(HelloService.class)  
  14. @ConditionalOnProperty(prefix = "hello",value = "enabled",matchIfMissing = true)  
  15. public class HelloServiceAutoConfiguration {  
  16.     @Autowired  
  17.     private HelloServiceProperties helloServiceProperties;  
  18.     @Bean  
  19.     @ConditionalOnMissingBean(HelloService.class)  
  20.     public HelloService helloService(){  
  21.         HelloService helloService = new HelloService();  
  22.         helloService.setMsg(helloServiceProperties.getMsg());  
  23.         return helloService;  
  24.     }  
  25. }  


    根据HelloServiceProperties提供的参数,并经过@ConditionalOnClass判断HelloService这个类在此类路径中是否存在,且当容器总没有这个Bean的状况下自动配置这个Bean


5,注册配置

    若想自动配置生效,须要注册自动配置类,在src/main/resources下新建META-INF/spring.factories,结构以下:



   在spring.factories中填写以下内容注册:

[plain]  view plain  copy
  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  
  2. com.jack.springboot.starter.hello.HelloServiceAutoConfiguration  

  如有多个自动配置,则用“,”隔开,此处是为了换行后仍然能读到属性。


6,测试

    在其余项目添加starter做为依赖,修改pom.xml添加依赖,代码以下:

[plain]  view plain  copy
  1. <dependency>  
  2.             <groupId>com.jack</groupId>  
  3.             <artifactId>com.jack.springboot-starter-hello</artifactId>  
  4.             <version>1.0-SNAPSHOT</version>  
  5.         </dependency>  


    咱们能够在Maven的依赖中查看依赖:



    在开发阶段,咱们引入的依赖是springboot-starter-hello这个项目,在starter稳定以后,咱们能够将springboot-starter-hello经过mvn install安装到本地库,或将这个jar包发到Maven私服上。



测试代码以下;

[java]  view plain  copy
  1. package com.jack.controller;  
  2.   
  3. import com.jack.springboot.starter.hello.HelloService;  
  4. import org.springframework.beans.factory.annotation.Autowired;  
  5. import org.springframework.web.bind.annotation.RequestMapping;  
  6. import org.springframework.web.bind.annotation.RestController;  
  7.   
  8. @RestController  
  9. public class SpringBootStarterController {  
  10.   
  11.     @Autowired  
  12.     private HelloService helloService;  
  13.     @RequestMapping(value = "/start")  
  14.     public String start(){  
  15.         return helloService.sayHello();  
  16.     }  
  17. }  


    在代码中能够直接注入到HelloService的Bean,可是在项目中咱们并无配置这个Bean,这是经过自动注入配置完成的,在浏览器输入http://localhost:9090/start,效果以下所示:


    这时在application.yml配置配置msg的内容:

[plain]  view plain  copy
  1. server:  
  2.   port: 9090  
  3.   
  4. hello:  
  5.   msg: jack  


重启,进行测试,效果以下:


若是在application.yml中开启debug=true,则能够查看到自动配置报告。