Spring Boot 源码分析 (一)

 2019-10-17 21:54  阅读(1083)
文章分类:Spring boot

请尊重作者劳动成果,转载请标明原文链接:http://www.cnblogs.com/dylan-java/p/7450914.html

启动SpringBoot,需要在入口函数所在的类上添加@SpringBootApplication注解

1 @SpringBootApplication
    2 public class Application {
    3     public static void main(String[] args) {
    4         SpringApplication.run(Application.class, args);
    5     }
    6 }

我们来看一下@SpringBootApplication注解

@Target(ElementType.TYPE)
     2 @Retention(RetentionPolicy.RUNTIME)
     3 @Documented
     4 @Inherited
     5 @SpringBootConfiguration
     6 @EnableAutoConfiguration
     7 @ComponentScan(excludeFilters = {
     8         @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
     9         @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    10 public @interface SpringBootApplication {
    11     @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
    12     Class<?>[] exclude() default {};
    13 
    14     @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
    15     String[] excludeName() default {};
    16 
    17     @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    18     String[] scanBasePackages() default {};
    19 
    20     @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    21     Class<?>[] scanBasePackageClasses() default {};
    22 }

1 @Target(ElementType.TYPE)
    2 @Retention(RetentionPolicy.RUNTIME)
    3 @Documented
    4 @Configuration
    5 public @interface SpringBootConfiguration {
    6 }

从上面的代码可以看出@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan

@Configuration注解(可以理解为xml里面的beans>标签),一般和@Bean注解(可以理解为xml里面的标签)搭配使用。使用这2个注解可以创建一个配置类,示例如下

[20191017100258\_1.png

1 @Configuration 2 public class Config { 3 @Bean 4 public People people() { 5 People people = new People(); 6 people.setAge(26); 7 people.setName("Dylan"); 8 people.setGender(1); 9 return people; 10 } 11 }

20191017100258\_2.png

可以替代xml配置文件里

20191017100258\_3.png

1 <beans> 2 <bean id="people" class="com.dylan.java.beans.People"> 3 <property name="age" value="26"></property> 4 <property name="name" value="Dylan"></property> 5 <property name="gender" value="1"></property> 6 </bean> 7 </beans>

@EnableAutoConfiguration注解自动载入应用程序所需要的所有Bean,这依赖于SpringBoot在类路径中的查找

20191017100258\_4.png

1 @SuppressWarnings("deprecation") 2 @Target(ElementType.TYPE) 3 @Retention(RetentionPolicy.RUNTIME) 4 @Documented 5 @Inherited 6 @AutoConfigurationPackage 7 @Import(EnableAutoConfigurationImportSelector.class) 8 public @interface EnableAutoConfiguration { 9 String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; 10 11 Class<?>[] exclude() default {}; 12 13 String[] excludeName() default {}; 14 }

20191017100258\_5.png

@EnableAutoConfiguration注解使用@Import注解导入EnableAutoConfigurationImportSelector类,此类继承了AutoConfigurationImportSelector类,而AutoConfigurationImportSelector类的selectImports方法就是关键所在

@Override 2 public String[] selectImports(AnnotationMetadata annotationMetadata) { 3 if (!isEnabled(annotationMetadata)) { 4 return NO_IMPORTS; 5 } 6 try { 7 AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader 8 .loadMetadata(this.beanClassLoader); 9 AnnotationAttributes attributes = getAttributes(annotationMetadata); 10 List<String> configurations = getCandidateConfigurations(annotationMetadata, 11 attributes); 12 configurations = removeDuplicates(configurations); 13 configurations = sort(configurations, autoConfigurationMetadata); 14 Set<String> exclusions = getExclusions(annotationMetadata, attributes); 15 checkExcludedClasses(configurations, exclusions); 16 configurations.removeAll(exclusions); 17 configurations = filter(configurations, autoConfigurationMetadata); 18 fireAutoConfigurationImportEvents(configurations, exclusions); 19 return configurations.toArray(new String[configurations.size()]); 20 } 21 catch (IOException ex) { 22 throw new IllegalStateException(ex); 23 } 24 }

20191017100258\_6.png
20191017100258\_7.png

1 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, 2 AnnotationAttributes attributes) { 3 List<String> configurations = SpringFactoriesLoader.loadFactoryNames( 4 getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); 5 Assert.notEmpty(configurations, 6 "No auto configuration classes found in META-INF/spring.factories. If you " 7 + "are using a custom packaging, make sure that file is correct."); 8 return configurations; 9 }

20191017100258\_8.png

1 protected Class<?> getSpringFactoriesLoaderFactoryClass() { 2 return EnableAutoConfiguration.class; 3 }

可以看出,该方法使用了Spring Core包的SpringFactoriesLoader类的loadFactoryNames方法,该方法会查询classpath下的JAR文件中包含的/META/spring.factories文件,从文件中读取配置文件名(这里是org.springframework.boot.autoconfigure.EnableAutoConfiguration)的属性,例如

在jar:file:/C:/Users/guiqingqing/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/1.5.6.RELEASE/spring-boot-autoconfigure-1.5.6.RELEASE.jar!/META-INF/spring.factories文件找到如下配置

20191017100258\_9.png

# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\ org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\ org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\ org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\ org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\ org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\ org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\ org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\ org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\ org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\ org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\ org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

20191017100258\_10.png

获取自动配置的类之后调用removeDuplicates方法先去除重复,然后调用sort方法进行排序,接下来调用getExclusions方法获取配置的exclude的类,比如@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}),然后这些exclude的类也会被排除

然后是调用filter方法,该方法决定哪些bean自动配置,哪些不配置。去classpath下的JAR文件中包含的/META/spring.factories文件里查询org.springframework.boot.autoconfigure.AutoConfigurationImportFilter对应的配置,这里找到的是org.springframework.boot.autoconfigure.condition.OnClassCondition,检查规则如下

经过上面的去重,排序,排除,(这里会有2个线程分别对前一半和后一半做检查)遍历所有剩下的class

首先看是否有@ConditionalOnClass注解,如果没有那么不过滤,表示需要配置这个bean

如果有@ConditionalOnClass注解再看这个注解依赖的类是否为空,如果为空,那么也不过滤,表示需要配置这个bean

如果@ConditionalOnClass注解依赖的类不为空,那么再看classpath下能不能找到这个依赖的类,如果能找不到,那么也不过滤,表示需要配置这个bean,否则过滤,表示不配置这个bean

例如FreeMarkerAutoConfiguration类

1 @Configuration 2 @ConditionalOnClass({ freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class }) 4 @AutoConfigureAfter(WebMvcAutoConfiguration.class) 5 @EnableConfigurationProperties(FreeMarkerProperties.class) 6 public class FreeMarkerAutoConfiguration { 7 }

该类的@ConditionalOnClass注解里有freemarker.template.Configuration.class和FreeMarkerConfigurationFactory.class类,如果classpath下能找到这2个类,那么就会自动加载FreeMarkerAutoConfiguration类

最后去classpath下的JAR文件中包含的/META/spring.factories文件里查询org.springframework.boot.autoconfigure.AutoConfigurationImportListener对应的属性作为监听器,然后发布一个AutoConfigurationImportEvent事件

最后交代一下,selectImports方法的调用时机,是在SpringBoot启动时,AbstractApplicationContext类refresh方法 -> invokeBeanFactoryPostProcessors方法 -> PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors方法 -> invokeBeanDefinitionRegistryPostProcessors方法 -> ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法 -> processConfigBeanDefinitions方法 -> ConfigurationClassParser类的parse方法 -> processDeferredImportSelectors方法

20191017100258\_11.png

1 private void processDeferredImportSelectors() { 2 List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors; 3 this.deferredImportSelectors = null; 4 Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR); 5 6 for (DeferredImportSelectorHolder deferredImport : deferredImports) { 7 ConfigurationClass configClass = deferredImport.getConfigurationClass(); 8 try { 9 String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata()); 10 processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false); 11 } 12 catch (BeanDefinitionStoreException ex) { 13 throw ex; 14 } 15 catch (Throwable ex) { 16 throw new BeanDefinitionStoreException( 17 "Failed to process import candidates for configuration class [" + 18 configClass.getMetadata().getClassName() + "]", ex); 19 } 20 } 21 }

20191017100258\_12.png

@ComponentScan注解会自动扫描指定包(如果不指定,那么默认扫描当前类路径以及子路径下的所有类)下的全部标有@Component(包括@Service、@Repository、@Controller等子注解)的类,并注册成bean

来源:[]()]beans_Bean_xml_2

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Spring Boot 源码分析 (一)

相关推荐