在看本节文章之前,倡议大家先去了一下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机制,次要蕴含:

  1. ApplicationContextInitializer:用于在spring容器刷新之前初始化Spring ConfigurableApplicationContext的回调接口。
  2. ApplicationListener:用于解决容器初始化各个阶段的事件。
  3. AutoConfigurationImportListener:导入配置类的时候,获取类的详细信息(Listener that can be registered with spring.factories to receive details of imported auto-configurations.)。
  4. 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.)
  5. 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).
  6. 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.)
  7. 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的实现。我的项目目录构造如下:

以下为各个文件的内容:

  1. DemoService

    public interface DemoService { void printName();}
  2. PrintDemoService

    @Servicepublic 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();     } }}
  3. DemoServiceImpl1
public class DemoServiceImpl1 implements DemoService {    @Override    public void printName() {        System.out.println("This is in demo 1.");    }}
  1. DemoServiceImpl2
public class DemoServiceImpl2 implements DemoService {    @Override    public void printName() {        System.out.println("This is in demo 2.");    }}
  1. FactoriesApplication
@SpringBootApplicationpublic class FactoriesApplication {    public static void main(String[] args) {        SpringApplication.run(FactoriesApplication.class, args);    }}
  1. spring.factories

    com.wangzemin.learning.factories.interfac.DemoService=\  com.wangzemin.learning.factories.impl.DemoServiceImpl1,\  com.wangzemin.learning.factories.impl.DemoServiceImpl2

程序的运行后果如下图所示,能够看到,Factories机制曾经胜利发挥作用。

附录:spring boot 自带factories文件示例

# Initializersorg.springframework.context.ApplicationContextInitializer=\org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener# Application Listenersorg.springframework.context.ApplicationListener=\org.springframework.boot.autoconfigure.BackgroundPreinitializer# Auto Configuration Import Listenersorg.springframework.boot.autoconfigure.AutoConfigurationImportListener=\org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener# Auto Configuration Import Filtersorg.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\org.springframework.boot.autoconfigure.condition.OnBeanCondition,\org.springframework.boot.autoconfigure.condition.OnClassCondition,\org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition# Auto Configureorg.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 analyzersorg.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 providersorg.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多平台公布