Spring Boot自动注入的原理分析
作者:李斯特王 发布时间:2023-03-29 04:19:44
前言
我们经常会被问到这么一个问题:SpringBoot相对于spring有哪些优势呢?其中有一条答案就是SpringBoot自动注入。那么自动注入的原理是什么呢?
我们进行如下分析。
1:首先我们分析项目的启动类时,发现都会加上@SpringBootApplication这个注解,我们分析这个继续进入这个注解会发现,它是由多个注解组成的,如下
@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 {
2:服务启动会扫描 org.springframework.boot.autoconfigure
下的 META-INF/spring.factories 这个文件,这个文件中保存着springboot 启动时默认会自动注入的类,部分如下
# 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
3:你是不是在其中发现了自己常用的redis,mysql等相关的类?没错,springboot会尝试加载这些类,我们以 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
这个类为例,进去看一下它的源码,部分示例如下
@Configuration
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
/**
* Redis connection configuration.
*/
@Configuration
@ConditionalOnClass(GenericObjectPool.class)
protected static class RedisConnectionConfiguration {
private final RedisProperties properties;
private final RedisSentinelConfiguration sentinelConfiguration;
private final RedisClusterConfiguration clusterConfiguration;
public RedisConnectionConfiguration(RedisProperties properties,
ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,
ObjectProvider<RedisClusterConfiguration> clusterConfiguration) {
this.properties = properties;
this.sentinelConfiguration = sentinelConfiguration.getIfAvailable();
this.clusterConfiguration = clusterConfiguration.getIfAvailable();
}
@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
public JedisConnectionFactory redisConnectionFactory()
throws UnknownHostException {
return applyProperties(createJedisConnectionFactory());
}
我们能看到这个类上加了这个注解 @ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
意思就是如果你的classpath中没有这些类的话,那么这个类就不能被加载,那么这些被依赖的类在哪出现呢?没错,就在我们在pom.xml中引入的依赖所对应的包里。
看到这里你因该就明白了,META-INF/spring.factories 文件中被列出来的那些类都会被springboot去尝试加载,但是有些模块我们没引入相关的依赖,那么这个类就会加载失败。即这个模块没有被成功加载。
4:我们通过上面的redis的自动加载类时,看到上面还有个 @EnableConfigurationProperties(RedisProperties.class)
注解,这个注解来注入关于redis的配置信息,这个信息都在 RedisProperties.class
中保存,我们看下 RedisProperties的源码
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
/**
* Database index used by the connection factory.
*/
private int database = 0;
/**
* Redis url, which will overrule host, port and password if set.
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
/**
* Enable SSL.
*/
private boolean ssl;
/**
* Connection timeout in milliseconds.
*/
private int timeout;
private Pool pool;
private Sentinel sentinel;
private Cluster cluster;
public int getDatabase() {
return this.database;
}
public void setDatabase(int database) {
this.database = database;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isSsl() {
return this.ssl;
}
public void setSsl(boolean ssl) {
this.ssl = ssl;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return this.timeout;
}
public Sentinel getSentinel() {
return this.sentinel;
}
public void setSentinel(Sentinel sentinel) {
this.sentinel = sentinel;
}
public Pool getPool() {
return this.pool;
}
public void setPool(Pool pool) {
this.pool = pool;
}
public Cluster getCluster() {
return this.cluster;
}
public void setCluster(Cluster cluster) {
this.cluster = cluster;
}
/**
* Pool properties.
*/
public static class Pool {
/**
* Max number of "idle" connections in the pool. Use a negative value to indicate
* an unlimited number of idle connections.
*/
private int maxIdle = 8;
/**
* Target for the minimum number of idle connections to maintain in the pool. This
* setting only has an effect if it is positive.
*/
private int minIdle = 0;
/**
* Max number of connections that can be allocated by the pool at a given time.
* Use a negative value for no limit.
*/
private int maxActive = 8;
/**
* Maximum amount of time (in milliseconds) a connection allocation should block
* before throwing an exception when the pool is exhausted. Use a negative value
* to block indefinitely.
*/
private int maxWait = -1;
public int getMaxIdle() {
return this.maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMinIdle() {
return this.minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public int getMaxActive() {
return this.maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMaxWait() {
return this.maxWait;
}
public void setMaxWait(int maxWait) {
this.maxWait = maxWait;
}
}
/**
* Cluster properties.
*/
public static class Cluster {
/**
* Comma-separated list of "host:port" pairs to bootstrap from. This represents an
* "initial" list of cluster nodes and is required to have at least one entry.
*/
private List<String> nodes;
/**
* Maximum number of redirects to follow when executing commands across the
* cluster.
*/
private Integer maxRedirects;
public List<String> getNodes() {
return this.nodes;
}
public void setNodes(List<String> nodes) {
this.nodes = nodes;
}
public Integer getMaxRedirects() {
return this.maxRedirects;
}
public void setMaxRedirects(Integer maxRedirects) {
this.maxRedirects = maxRedirects;
}
}
/**
* Redis sentinel properties.
*/
public static class Sentinel {
/**
* Name of Redis server.
*/
private String master;
/**
* Comma-separated list of host:port pairs.
*/
private String nodes;
public String getMaster() {
return this.master;
}
public void setMaster(String master) {
this.master = master;
}
public String getNodes() {
return this.nodes;
}
public void setNodes(String nodes) {
this.nodes = nodes;
}
}
}
发现里面的配置项基本都是有默认值的,通过上面的注解可以明白,如果配置文件中存在 spring.redis 开头的配置项,则使用配置文件中的,如果没有的话则使用文件中默认写死的配置。你是不是想到了springboot的另外一个优势:约定大于配置。
这里我们大概了解了SpringBoot自动配置的原理和流程,里面的那些细节我们不在分析。同理,对于那些第三方或者我们自己写的starter,springboot启动的时候会扫描starter的jar包下 META-INF/spring.factories 这个文件,解析内容并加载里面对用的类。
由此,我们总结出以下几点
1:SpringBoot的自动配置是如何实现的
2:有关的那些注解,如@EnableAutoConfiguration, @ConditionalOnClass, @Configuration等也是SpringBoot的核心注解,也值得我们了解其用法和原理。
来源:https://www.cnblogs.com/wanghaoyang/p/11693973.html
猜你喜欢
- CompletableFuture 介绍CompletableFuture是1.8引入的新特性,一些比较复杂的异步计算场景,尤其是需要串联多
- 背景最近好几个项目在运行过程中客户都提出文件上传大小的限制能否设置的大一些,用户经常需要上传好几个G的资料文件,如图纸,视频等,并且需要在上
- Android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在Android的开发中是必不可少的,占着举足轻重
- 正则表达式是一种描述词素的重要表示方法。虽然正则表达式并不能表达出所有可能的模式(例如“由等数量的 a 和 b 组成的字符串”),但是它可以
- 以前使用HttpServletResponse可以通过输出流的方式来向前台输出图片。现在大部分都是使用springboot,在使用sprin
- 一、流程和任务的关系以下是一个简单的请假流程图,其中有一个开始事件,两个用户任务,一个结束事件。启动流程后,activiti会自动创建第一个
- public void add(intindex, Eelement)从index索引的位置添加element元素,后面的元素都往
- 【SpringBoot】通过Feign调用传递Header中参数如何通过Feign传递Header参数问题描述我们在SpringCloud中
- 这篇文章主要介绍了JAVA实现账户取款和存款操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以
- java Mybatis存进时间戳封装了一个实体类,里面有个字段 Integer createTime。要利用这个实体类将一个时间戳存进数据
- 实现“摇一摇”功能,其实很简单,就是检测手机的重力感应,具体实现代码如下:1、在 AndroidManifest.xml 中添加操作权限2、
- java 实现MD5加密算法的简单实例实现代码:import java.security.NoSuchAlgorithmException;
- timer和timertask是jdk自带的定时任务实现,无需导入第三方jar包来完成1、指定多久之后执行此任务,注意:只会执行一次publ
- 本文实例总结了Android开发中Toast显示消息的方法。分享给大家供大家参考,具体如下:Android中提供一种简单的Toast消息提示
- 前言java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也不能做出来非常好用,
- 1. 创建全局异常处理器类GlobalExceptionHandler@ControllerAdvice: 定义统一的异常处理类,捕获 Co
- 第一种方法:string s=abcdeabcdeabcde;string[] sArray=s.Split(c) ;foreach(str
- Mybatis基础回顾与高级应用数据库:mysql5.7jdk:15引入依赖<!--引入依赖--> &
- autoMapping和autoMappingBehavior的区别autoMappingBehaviormybatis核心配置文件中set
- Handler、Message、Loopler、MessageQueen首先看一下我们平常使用Handler的一个最常见用法。Handler