您好,登錄后才能下訂單哦!
前言
我們經(jīng)常會(huì)被問(wèn)到這么一個(gè)問(wèn)題:SpringBoot相對(duì)于spring有哪些優(yōu)勢(shì)呢?其中有一條答案就是SpringBoot自動(dòng)注入。那么自動(dòng)注入的原理是什么呢?
我們進(jìn)行如下分析。
1:首先我們分析項(xiàng)目的啟動(dòng)類時(shí),發(fā)現(xiàn)都會(huì)加上@SpringBootApplication這個(gè)注解,我們分析這個(gè)繼續(xù)進(jìn)入這個(gè)注解會(huì)發(fā)現(xiàn),它是由多個(gè)注解組成的,如下
@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:服務(wù)啟動(dòng)會(huì)掃描 org.springframework.boot.autoconfigure
下的 META-INF/spring.factories 這個(gè)文件,這個(gè)文件中保存著springboot 啟動(dòng)時(shí)默認(rèn)會(huì)自動(dòng)注入的類,部分如下
# 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.h3.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.oauth3.OAuth3AutoConfiguration,\ 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:你是不是在其中發(fā)現(xiàn)了自己常用的redis,mysql等相關(guān)的類?沒(méi)錯(cuò),springboot會(huì)嘗試加載這些類,我們以 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
這個(gè)類為例,進(jìn)去看一下它的源碼,部分示例如下
@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()); }
我們能看到這個(gè)類上加了這個(gè)注解 @ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
意思就是如果你的classpath中沒(méi)有這些類的話,那么這個(gè)類就不能被加載,那么這些被依賴的類在哪出現(xiàn)呢?沒(méi)錯(cuò),就在我們?cè)趐om.xml中引入的依賴所對(duì)應(yīng)的包里。
看到這里你因該就明白了,META-INF/spring.factories 文件中被列出來(lái)的那些類都會(huì)被springboot去嘗試加載,但是有些模塊我們沒(méi)引入相關(guān)的依賴,那么這個(gè)類就會(huì)加載失敗。即這個(gè)模塊沒(méi)有被成功加載。
4:我們通過(guò)上面的redis的自動(dòng)加載類時(shí),看到上面還有個(gè) @EnableConfigurationProperties(RedisProperties.class)
注解,這個(gè)注解來(lái)注入關(guān)于redis的配置信息,這個(gè)信息都在 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; } } }
發(fā)現(xiàn)里面的配置項(xiàng)基本都是有默認(rèn)值的,通過(guò)上面的注解可以明白,如果配置文件中存在 spring.redis 開(kāi)頭的配置項(xiàng),則使用配置文件中的,如果沒(méi)有的話則使用文件中默認(rèn)寫死的配置。你是不是想到了springboot的另外一個(gè)優(yōu)勢(shì):約定大于配置。
這里我們大概了解了SpringBoot自動(dòng)配置的原理和流程,里面的那些細(xì)節(jié)我們不在分析。同理,對(duì)于那些第三方或者我們自己寫的starter,springboot啟動(dòng)的時(shí)候會(huì)掃描starter的jar包下 META-INF/spring.factories 這個(gè)文件,解析內(nèi)容并加載里面對(duì)用的類。
由此,我們總結(jié)出以下幾點(diǎn)
1:SpringBoot的自動(dòng)配置是如何實(shí)現(xiàn)的
2:有關(guān)的那些注解,如@EnableAutoConfiguration, @ConditionalOnClass, @Configuration等也是SpringBoot的核心注解,也值得我們了解其用法和原理。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。