springboot-自动装配

本次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我们可以打破双亲委派机制,来达到自己的实现。













原文地址:https://www.cnblogs.com/tdyang/p/13998367.html