SpringBoot自动注入分析
我们经常会被问到这么一个问题: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的核心注解,也值得我们了解其用法和原理。
SpringBoot自动注入分析的更多相关文章
- 原创001 | 搭上SpringBoot自动注入源码分析专车
		前言 如果这是你第二次看到师长的文章,说明你在觊觎我的美色!O(∩_∩)O哈哈~ 点赞+关注再看,养成习惯 没别的意思,就是需要你的窥屏^_^ 本系列为SpringBoot深度源码专车系列,第一篇发车 ... 
- SpringBoot 为什么能够自动的注入一些常用的Bean ?详细分析SpringBoot 自动配置的实现
		转载至:https://blog.csdn.net/qq_29941401/article/details/79605388 有一个问题一直让我好奇,为什么在SpringBoot中有的bean 我们都 ... 
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
		SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ... 
- SpringBoot启动流程分析(六):IoC容器依赖注入
		SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ... 
- 深入理解springboot的自动注入
		一.开篇 在平时的开发过程中用的最多的莫属springboot了,都知道springboot中有自动注入的功能,在面试过程中也会问到自动注入,你知道自动注入是怎么回事吗,springboot是如何 ... 
- 数据库连接不上的原因以及springBoot的ioc无法自动注入
		无法自动注入解决了,数据池的连接还有问题: 错误原因1: :数据库用的是Mysql8版本,以前的配置mysql驱动包却是5.1.37版本.只需修改驱动包为8.0.11版本即可. <!-- mys ... 
- 关于springboot项目中自动注入,但是用的时候值为空的BUG
		最近想做一些web项目来填充下业余时间,首先想到了使用springboot框架,毕竟方便 快捷 首先:去这里 http://start.spring.io/ 直接构建了一个springboot初始化的 ... 
- 【SpringBoot】SpringBoot热部署和配置文件自动注入实战
		========================3.SpringBoot热部署devtool和配置文件自动注入实战 ============================ 1.SpringBoot2 ... 
- springboot自动配置国际化失效分析
		最近在整理springBoot国际化时,发现国际化没有生效,通过报错提示在 MessageTag -> doEndTag处打断点 最后发现messageSource并不是ResourceBund ... 
随机推荐
- Spring Cloud Alibaba | 微服务分布式事务之Seata
			Spring Cloud Alibaba | 微服务分布式事务之Seata 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Green ... 
- 使用secureCRT进行linux和windows之间的nginx文件夹传输
			1.首先进入secureCRT软件,新建一个链接,我现在已经创建好了进入这个页面: 注意:新建链接时里面的hostname是你linux的ip地址,使用ifconfig就可以看到 2.在secureC ... 
- 【LeetCode】Two Sum II - Input array is sorted
			[Description] Given an array of integers that is already sorted in ascending order, find two numbers ... 
- C# Post Get 方式发送请求
			httpPost 方式发送请求 不带参数 /// <summary> /// 没有参数的post请求 /// </summary> public void HttpPostNo ... 
- 手写RPC框架指北另送贴心注释代码一套
			Angular8正式发布了,Java13再过几个月也要发布了,技术迭代这么快,框架的复杂度越来越大,但是原理是基本不变的.所以沉下心看清代码本质很重要,这次给大家带来的是手写RPC框架. 完整代码以及 ... 
- DevExpress的TextEdit限制输入内容的格式,比如只能输入数字
			场景 Winform控件-DevExpress18下载安装注册以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1 ... 
- 编写自动匹配的下拉框(已解决IE8兼容)
			如何制作一个带匹配功能的下拉框? 之前看见layui有相关组件,但是发现,如果输入的内容在下拉框中没有相应的匹配,就会清空当前值,搞得我很不满意.有些代码是从网上扒下来的,但是找不到原地址了,凑合看吧 ... 
- centos7下mysql 用户管理和权限设置
			1.进入mysql命令行,输入root及密码[root@localhost ~]# mysql -u root -pEnter password: Welcome to the MySQL monit ... 
- 40  (OC)*  数据库常见sql语句
			1:增加INSERT INTO t_student (name, age) VALUES ('liwx', 18);2:删除DELETE FROM t_student WHERE name = 'li ... 
- .netCore+Vue 搭建的简捷开发框架
			话不多说,上图: 整体项目结构如图所示,我的设计初衷是基于.netCore + DI + Vue 打造一个适合初学者的简捷开发框架. 架构模型采用基于RESTful API风格的前后台分离框架,总体分 ... 
