在看本节文章之前,倡议大家先去了一下 java 的 SPI 机制,因为 Spring 的 Factories 就是 Spring 版本的 Java Spi,我在对于 java 根底系列文章中有具体介绍 Java SPI 机制。Spring Factories 的最重要的性能就是:能够通过配置文件指定 Spring 容器加载一些特定的组件。
<!–more–>
基本概念
什么是 Spring Factories
Spring Factories 是一种相似于 Java SPI 的机制,它在 META-INF/spring.factories 文件中配置接口的实现类名称,而后在程序中读取这些配置文件并实例化。
援用自博客:Java SPI 次要是利用于厂商自定义组件或插件中。在 java.util.ServiceLoader 的文档里有比拟具体的介绍。简略的总结下 java SPI 机制的思维:咱们零碎里形象的各个模块,往往有很多不同的实现计划,比方日志模块、xml 解析模块、jdbc 模块等计划。面向的对象的设计里,咱们个别举荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里波及具体的实现类,就违反了可拔插的准则,如果须要替换一种实现,就须要批改代码。为了实现在模块拆卸的时候能不在程序里动静指明,这就须要一种服务发现机制。Java SPI 就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点相似 IOC 的思维,就是将拆卸的控制权移到程序之外,在模块化设计中这个机制尤其重要。
为什么要有 Spring Factories
Spring Factories 机制提供了一种解耦容器注入的形式,帮忙内部包(独立于 spring-boot 我的项目)注册 Bean 到 spring boot 我的项目容器中。
问题:如果想要被 Spring 容器治理的 Bean 的门路不再 Spring Boot 我的项目的扫描门路下,那该怎么办呢?
一般解法 1:在 Spring Boot 我的项目中配置 ComponentScan 注解的扫描门路,增加须要被扫描的办法。
一般解法 2:通过在 Spring Boot 我的项目中增加 @EnableAutoConfiguration 注解,并自定义 @EnableXXXXConfiguration 的注解,通过注解中的办法注入 Bean。
一般解法 3:在 Spring Boot 我的项目中 xxxx……………..。
这些解法次要思维都如下图所示,尽管曾经实现了帮忙内部包(独立于 spring-boot 我的项目)注册 Bean 到 spring boot 我的项目容器中的性能,然而 Spring Boot 我的项目都须要晓得内部包的信息,并在其代码中引入内部包的相干逻辑,如果内部包变更的状况下,Spring Boot 我的项目也须要跟着变更,Spring Boot 和内部包实现间接存在紧耦合关系。
Spring Factories 机制解法:
在 内部包 的 META-INF/spring.factories 文件中增加配置文件,Spring Boot 我的项目会主动扫描这个配置文件,获取内部包的 Bean 的详细信息。根本思维如下图所示,从图中能够看到,Spring Boot 我的项目中曾经不蕴含内部包的相干逻辑,实现与内部包之间的解耦关系。
Spring Factories 机制原理
外围类 SpringFactoriesLoader
从上文可知,Spring Factories 机制通过 META-INF/spring.factories 文件获取相干的实现类的配置信息,而 SpringFactoriesLoader 的性能就是读取 META-INF/spring.factories,并加载配置中的类。SpringFactoriesLoader 次要有两个办法:loadFactories 和 loadFactoryNames。
SpringFactoriesLoader 官网阐明 : General purpose factory loading mechanism for internal use within the framework.
META-INF/spring.factories 中定义了实现类和对应的接口之间的关系,其定义格局如下:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2
其中的 example.MyService 为接口全称,example.MyServiceImpl1,example.MyServiceImpl2 为两个实现类的全称。官网阐明:SpringFactoriesLoader loads and instantiates factories of a given type from META-INF/spring.factories files which may be present in multiple JAR files in the classpath. The file must be in {@link Properties} format, where the key is the fully qualified name of the interface or abstract class, and the value is a comma-separated list of implementation class names. For example:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2
where {@code example.MyService} is the name of the interface, and {@code MyServiceImpl1} and {@code MyServiceImpl2} are two implementations.
loadFactoryNames
用于按接口获取 Spring Factories 文件中的实现类的全称,其办法定义如下所示,其中参数 factoryType 指定了须要获取哪个接口的实现类,classLoader 用于读取配置文件资源。public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader)
loadFactories
用于按接口获取 Spring Factories 文件中的实现类的实例,其办法定义如下所示,其中参数 factoryType 指定了须要获取哪个接口的实现类,classLoader 用于读取配置文件资源和加载类。public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader)
Spring Boot Factories
Spring boot 中默认应用了很多 factories 机制,次要蕴含:
- ApplicationContextInitializer:用于在 spring 容器刷新之前初始化 Spring ConfigurableApplicationContext 的回调接口。
- ApplicationListener:用于解决容器初始化各个阶段的事件。
- AutoConfigurationImportListener:导入配置类的时候,获取类的详细信息(Listener that can be registered with spring.factories to receive details of imported auto-configurations.)。
- AutoConfigurationImportFilter:用于按条件过滤导入的配置类(Filter that can be registered in spring.factories to limit the auto-configuration classes considered. This interface is designed to allow fast removal of auto-configuration classes before their bytecode is even read.)
- EnableAutoConfiguration:指定主动加载的配置类列表(Enable auto-configuration of the Spring Application Context, attempting to guess and configure beans that you are likely to need. Auto-configuration classes are usually applied based on your classpath and what beans you have defined. For example, if you have tomcat-embedded.jar on your classpath you are likely to want a TomcatServletWebServerFactory (unless you have defined your own ServletWebServerFactory bean).
- FailureAnalyzer:在启动时拦挡异样并将其转换为易读的音讯,并将其蕴含在 FailureAnalysis 中。Spring Boot 为应用程序上下文相干异样、JSR-303 验证等提供了此类分析器(A FailureAnalyzer is used to analyze a failure and provide diagnostic information that can be displayed to the user.)
- TemplateAvailabilityProvider:模版引擎配置。(Collection of TemplateAvailabilityProvider beans that can be used to check which (if any) templating engine supports a given view. Caches responses unless the spring.template.provider.cache property is set to false.)
自定义 Spring Factories 机制
本节将应用一个例子来展现 Spring Factories 机制,案例分为两个我的项目 spring-factories-provider 和 spring-factories-consume,其中 spring-factories-consume 能够类比于上文中的 Spring Boot 我的项目,蕴含 Bean 的接口和 Bean 的调用,spring-factories-provider 能够类比于内部包,蕴含了 bean 的实现。我的项目目录构造如下:
以下为各个文件的内容:
-
DemoService
public interface DemoService {void printName(); }
-
PrintDemoService
@Service public class PrintDemoService { @PostConstruct public void printService(){List<String> serviceNames = SpringFactoriesLoader.loadFactoryNames(DemoService.class,null); for (String serviceName:serviceNames){System.out.println(serviceName); } List<DemoService> services = SpringFactoriesLoader.loadFactories(DemoService.class,null); for (DemoService demoService:services){demoService.printName(); } } }
- DemoServiceImpl1
public class DemoServiceImpl1 implements DemoService {
@Override
public void printName() {System.out.println("This is in demo 1.");
}
}
- DemoServiceImpl2
public class DemoServiceImpl2 implements DemoService {
@Override
public void printName() {System.out.println("This is in demo 2.");
}
}
- FactoriesApplication
@SpringBootApplication
public class FactoriesApplication {public static void main(String[] args) {SpringApplication.run(FactoriesApplication.class, args);
}
}
-
spring.factories
com.wangzemin.learning.factories.interfac.DemoService=\ com.wangzemin.learning.factories.impl.DemoServiceImpl1,\ com.wangzemin.learning.factories.impl.DemoServiceImpl2
程序的运行后果如下图所示,能够看到,Factories 机制曾经胜利发挥作用。
附录:spring boot 自带 factories 文件示例
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# 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.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
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.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
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.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
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.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
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.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
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.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
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.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
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.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer,\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
我是御狐神,欢送大家关注我的微信公众号:wzm2zsd
本文由 mdnice 多平台公布