本次springboot版本:2.1.3.RELEASE
对于官方组件,是基于condition条件来决定对于类是否要自动装配,
对于第三方组件,是采用spi机制 来实现扩展
官方包命名一般是:spring-boot-starter-xxx,如spring-boot-starter-data-redis
第三方包命令一般是: xxx-spring-boot-starter,如mybatis-plus-boot-starter,pagehelper-spring-boot-starter
springboot的自动配置使得我们的开发更加的简单,我们在springboot中使用redis时,
只需要引入redis依赖,配置redis的地址等信息,然后在业务中@Autowired
@Autowired private RedisTemplate redisTemplate;
就可以使用redisTemplate去操作reids,那么说明redisTemplate已经在ioc容器中,但我们并没有手动去创建一个配置类
@Configuration public class RedisConfiguration { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
在spring中,我们可以在配置类中,使用@Bean,@Import,@ComponentScan等注解方式将组件注入到ioc中
https://www.cnblogs.com/tdyang/p/11867704.html
但在springboot中我们都没有这样做,那么它是如何注入到容器中的?
在springboot启动入口的类中,有一个@SpringBootApplication注解
@SpringBootApplication public class MyspringbootApplication { public static void main(String[] args) { SpringApplication.run(MyspringbootApplication.class, args); } }
点进SpringBootApplication我们可以看到:@EnableAutoConfiguration注解,启动自动装配
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {
点进EnableAutoConfiguration中:我们知道@Import可以将组件导入到容器中
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {
点进AutoConfigurationImportSelector中:实现了一些接口,
在spring中,我们可以通过实现ImportSelector接口,返回我们需要导入到ioc容器中的全类名称组件数组,然后通过@Import注解
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
DeferredImportSelector继承了ImportSelector
public interface DeferredImportSelector extends ImportSelector {
在AutoConfigurationImportSelector中的getConfigurations()可以获取到很多的自动配置类,这些配置类就是给容器中导入所需要的所有组件。
public List<String> getConfigurations() { return this.configurations; }
、
点进去其中的一个自动配置类RedisAutoConfiguration ,我们就可以看到RedisTemplate了
@ConditionalOnClass(RedisOperations.class),就是根据条件进行加载,当我们依赖了spring-boot-starter-data-redis
这个bean才会去创建
@Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) public class RedisAutoConfiguration { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } }
那么springboot是怎么知道要扫描哪些路径下的包呢?这里springboot给了一个约定:
springboot会去扫描classpath:META-INF/spring.factories路径下的包
对于官方的包:
我们没有发现有相关的文件,它放在了spring-boot-autoconfigure包下
它会去扫描这些路径进行自动装配。
# 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.CloudServiceConnectorsAutoConfiguration, 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.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.ElasticsearchAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, 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.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.jest.JestAutoConfiguration, org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, 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.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.groovy.template.GroovyTemplateAutoConfiguration, 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.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.reactor.core.ReactorCoreAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration, 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.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
对于springboot的第三方包:如mybatis,它会去扫描配置文件中的路径org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
导入需要的组件。
在springboot中除了使用@ConditionalOnClass等注解来实现按照条件来加载bean,还可以通过spring-autoconfigure-metadata.properties文件
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration.AutoConfigureAfter注入的bean,
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration注入的条件
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration.AutoConfigureAfter=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration.Configuration= org.springframework.boot.autoconfigure.data.neo4j.Neo4jBookmarkManagementConfiguration.Configuration= org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration= org.springframework.boot.autoconfigure.kafka.KafkaAnnotationDrivenConfiguration.Configuration= org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration.ConditionalOnClass=org.influxdb.InfluxDB
..........
既然知道了springboot的自动装配机制,那就可以自己写一个starter
1、首先创建一个maven项目:
2、把java和resource目录标记为Resource Root
3、在Resource 目录下创建META-INF/spring.factories
4、pom.xml引入spring-boot-starter
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.1.3.RELEASE</version> <optional>true</optional> </dependency>
5、写一个自定义的配置类:
MyRedisStarter
public class MyRedisStarter { public void print(){ System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<MyRedisStarter连接redis>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); } }
6、spring.factories文件中:
key是org.springframework.boot.autoconfigure.EnableAutoConfiguration
value是配置类的全路径名
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.atyoung.starter.atyoungspringbootstarter.MyRedisStarterConfiguration
7、maven先clean,然后install
8、在另外一个springboot项目中引用
9、启动类中,获取到MyRedisStarter ,并调用print()方法
这样一个基础的starter就完成了。
一开始讲到自动装配是采用spi机制来实现扩展
spi:Service provider interface
是java为第三方提供的一种扩展机制,例如java的java.sql.Driver接口有很多驱动实现
如mysql,orcale等第三方厂商提供的实现,其机制是和上面的差不多。
简单的写一个实现java.sql.Driver的数据库驱动的demo
1、首先创建一个maven项目,将java和resource目录的设置和上面一样,为root
2、创建一个类,实现java.sql.Driver
3、在resources目录下:创建META-INF和services目录,创建文件java.sql.Driver,是接口全类名
4、文件里面是该接口的实现的全类名
5、maven进行clean和install
6、在别的项目里引用
7、在main方法中去获取到实现了java.sql.Driver的驱动实现
ServiceLoader<Driver> loaders = ServiceLoader.load(Driver.class); for (Driver driver : loaders){ System.out.println(driver); }
8、打印结果,可以看到自己写的驱动实现
这样一个简单的sqi扩展点就实现了。
利用spi我们可以打破双亲委派机制,来达到自己的实现。