SpringBoot初体验及原理解析

一、前言

?  我们来用SpringBoot开始HelloWorld之旅。SpringBoot是Spring框架对“约定大于配置(Convention over Configuration)”理念的最佳实践。SpringBoot应用本质上就是一个基于Spring框架的应用。我们大多数程序猿已经对Spring特别熟悉了,那随着我们的深入挖掘,会发现SpringBoot中并没有什么新鲜事,如果你不信,那就一起走着瞧呗!

二、SpringBoot初体验

首先,我们按照下图中的步骤生成一个SpringBoot项目:

  

解压后的项目文件在idea中打开以后,我们会看到如下的项目结构:

  

这时候,我们在com.hafiz.springbootdemo包下新建controller包,然后再在该包下面新建DemoController.java文件,内容如下:

package com.hafiz.springbootdemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author hafiz.zhang
 * @description: first spring boot controller
 * @date Created in 2018/6/3 16:49.
 */
@RestController
public class DemoController {

    @GetMapping("/hello")
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

然后我们运行SpringbootDemoApplication.java这个main方法,启动成功后,在控制台中会出现以下日志,证明项目启动成功:

  

我们从日志中可以看出,已经注册了get方式的/hello的路径以及名为/error的路径,并且项目在tomat中运行在8080端口,然后我们在浏览器中访问localhost:8080/hello?name=hafiz.zhang会看到如下信息:

这样我们就完成了demo项目的开发,先不用这里面到底发生了啥,我就想问问你:是不是很爽?完全没有传统项目的繁琐的xml配置,爽到爆有木有?搭建一个项目骨架只要几秒钟!这就是SpringBoot带给我们的便利~ 就是这么神奇!就是这么牛逼!

三、项目简单解析

首先我们来看,生成好的项目中的SpringbootDemoApplication.java文件,内容如下:

package com.hafiz.springbootdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootDemoApplication.class, args);
    }
}

代码很简单,但最耀眼的就是@SpringBootApplication注解以及在main方法中运行的SpringAppliation.run()了,那我们要揭开SpringBoot应用的奥秘,很明显就要拿这二位开刀了!

@SpringBootApplication注解解析

先看看@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 {
    ...
}

我们看到@SpringBootApplication其实是一个复合的注解,起主要作用的就是@SpringBootConfiguration@EnableAutoConfiguration以及@ComponentScan 三个注解组成,所以如果我们把SpringBoot启动类改写成如下方式,整个SpringBoot应用依然可以与之前的启动类功能一样:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public class SpringbootDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootDemoApplication.class, args);
    }
}

因为我们每次新建项目时都要写上三个注解来完成配置,这显然太繁琐了,SpringBoot就为我们提供了@SpringBootApplication这样一个复合注解来简化我们的操作。简直不能再贴心一点了!

@SpringBootConfiguration注解解析

接着我们来看@SpringBootConfiguration注解的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

我们可以看到,这里面依旧没有什么新东西,它SpringBoot为了区别@Configuration而新提供的专属于SpringBoot的注解,功能和@Configuration一模一样。而这里的@Configuration注解对于我们来说并不陌生,我们在上篇文章中进行了详细的介绍。SpringBoot的启动类标注了这个注解,毫无疑问,它本身也是个IoC容器的配置类。了解到了这里,我们其实可以把SpringBoot的启动类来拆成两个类,拆完以后就非常清楚明了了:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class DemoConfiguration {

}
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoConfiguration.class, args);
    }
}

所以呢,启动类DemoApplication其实就是一个标准的Standalone类型的Java程序的main函数启动类,也并没有什么特殊的东西。

@EnableAutoConfiguration 的神奇之处

看到这货,我们不仅联想出Spring 中很多以“@Enable”开头的注解,比如:@EnableScheduling@EnableCaching以及@EnableMBeanExport等,@EnableAutoConfiguration注解的理念和工作原理和它们其实一脉相承。简单的来说,就是该注解借助@Import注解的支持,Spring的IoC容器收集和注册特定场景相关的Bean定义:

  • @EnableScheduling是通过@Import将Spring调度框架相关的bean都加载到IoC容器。
  • @EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。

@EnableAutoConfiguration注解也是借助@Import将所有复合配置条件的bean定义加载到IoC容器,仅此而已!而@EnableAutoConfiguration注解的源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

这其中最关键的就是@Import(EnableAutoConfigurationImportSelector.class)了,它借助EnableAutoConfigurationImportSelector.class可以帮助SpringBoot应用将所有符合条件的@Configuration配置类都加载到当前SpringBoot创建并使用的IoC容器,就像一个“八爪鱼”一样。

  

下面我们给出EnableAutoConfigurationImportSelector.java的父类AutoConfigurationImportSelector.java的部分源码,来解释和验证上图:

public class AutoConfigurationImportSelector
        implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered {
    protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class,
                this.beanClassLoader);
    }
    protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class,
                this.beanClassLoader);
    }
}

以上源码可以看出,@EnableAutoConfiguration正是借助SpringFactoriesLoader的支持,才能完成如此伟大的壮举!

幕后英雄SpringFactoriesLoader详解

SpringFactoriesLoader属于Spring框架专属的一种扩展方案(其功能和使用方式类似于Java的SPI方案:java.util.ServiceLoader),它的主要功能就是从指定的配置文件META-INF/spring.factories中加载配置,spring.factories是一个非常经典的java properties文件,内容格式是Key=Value形式,只不过这Key以及Value都非常特殊,为Java类的完整类名(Fully qualified name),比如:

com.hafiz.service.DemoService=com.hafiz.service.impl.DemoServiceImpl,com.hafiz.service.impl.DemoServiceImpl2

然后Spring框架就可以根据某个类型作为Key来查找对应的类型名称列表了,SpringFactories源码如下:

public abstract class SpringFactoriesLoader {

    private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);

    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader){
        ...
    }

    public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        ...
    }
    // ...
}

对于@EnableAutoConfiguraion来说,SpringFactoriesLoader的用途和其本意稍微不同,它本意是为了提供SPI扩展,而在@EnableAutoConfiguration这个场景下,它更多的是提供了一种配置查找的功能的支持,也就是根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为Key来获取一组对应的@Configuration类:

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

在SpringBoot的autoconfigure依赖包中的META-INF文件下的spring.factories文件中,我们可以找到以上内容,这就很好的解释了为什么。

总结来说,@EnableAutoConfiguration能实现自动配置的原理就是:SpringFactoriesLoader从classpath中搜寻所有META-INF/spring.fatories文件,并将其中Key[org.springframework.boot.autoconfigure.EnableAutoConfiguration]对应的Value配置项通过反射的方式实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总到当前使用的IoC容器中。

非必须的@ComponentScan解析

为什么说这个注解是非必需的呢?因为我们知道作为Spring框架里的老成员,@ComponentScan的功能就是自动扫描并加载复合条件的组件或Bean定义,最终将这些bean定义加载到当前使用的容器中。这个过程,我们可以手工单个进行注册,不是一定要通过这个注解批量扫描和注册,所以说@ComponentScan是非必需的。

所以,如果我们当前应用没有任何bean定义需要通过@ComponentScan加载到当前SpringBoot应用对应的IoC容器,那么,去掉@ComponentScan注解,当前的SpringBoot应用依旧可以完美运行!那是不是到目前为止,依旧没有什么新鲜的事物出现?

关于我们用到的@RestController以及@GetMapping

@RestController注解也是一个复合注解,没啥新东西,就是自动返回json类型的数据,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    String value() default "";
}

@GetMapping注解也是一个复合注解,依旧没啥新东西,就是用来定义只支持GET请求的URL,源码如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
    ...
}
 

原文地址:https://www.cnblogs.com/lc1776/p/9139036.html

时间: 2024-10-07 06:14:52

SpringBoot初体验及原理解析的相关文章

Memcached初体验及原理讲解

1.简介 Memcached 是一个 高性能的 分布式 内存对象缓存系统,用于动态Web应用减少数据库负载,提升性能. 2.试用场景 1.变化频繁,具有不稳定性的数据 (比如用户在线状态.在线人数..) 2.门户网站的新闻等,觉得页面静态化仍不能满足要求,可以放入到memcache中. 什么样的数据不适合放入memcached中?(银行,股票,证券系统.) 过大的数据不能放入到memcache(优酷网.) --我自己的一个小结如何决定是否使用memcached --如果是一个小网站,pv值不大,

Memcached初体验及原理解说

1.简单介绍 Memcached 是一个 高性能的 分布式 内存对象缓存系统,用于动态Web应用降低数据库负载,提升性能. 2.试用场景 1.变化频繁,具有不稳定性的数据 (比方用户在线状态.在线人数..) 2.门户站点的新闻等,认为页面静态化仍不能满足要求,能够放入到memcache中. 什么样的数据不适合放入memcached中? (银行,股票.证券系统.) 过大的数据不能放入到memcache(优酷网.) --我自己的一个小结怎样决定是否使用memcached --假设是一个小站点,pv值

JSON初体验(三):FastJson解析

JSON解析之FastJson(阿里巴巴解析开源) 特点: Fastjson是一个Java语言编写的高性能功能完善的JSON库,它采用的 是一种"假定有序快速匹配"的算法,把JSON Parse的性能提升到极致, 是目前Java语言中最快的JSON库. 1.将json格式{}转换为Java对象 API: <T> T parseObject(String json,Class<T> classOfT); 步骤: 1.导入fastjson的jar包 2.JSON调用

使用Spring-boot初体验(待完善)

spring-boot 来开发应用,简直可以用桑心病狂来形容了.0 配置,让你欲罢不能呀!!运行Web 都不需要tomcat.直接 run 你的jar就可以.多余的就不说了,先上一些代码: 我使用的Maven,Maven具体内容如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schem

SpringBoot 初体验

1.Spring Boot 简介 简化Spring应用开发的一个框架 整个Spring技术栈的一个大整合 J2EE开发的一站式解决方案 2.微服务 2014, martin fowler 微服务:架构服务 (服务微化) 一个应用应该是一组小型服务:可以通过HTTP的方式进行互通 单体应用:ALL IN ONE 微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元 详细参照微服务文档 3.环境准备 环境约束 –jdk1.8:Spring Boot 推荐jdk1.7及以上:java ve

SpringBoot自动配置注解原理解析

1. SpringBoot启动主程序类: 1 @SpringBootApplication 2 public class DemoApplication { 3 public static void main(String[] args) { 4 5 SpringApplication.run(DemoApplication.class, args); 6 } 7 } 每次我们直接直接启动这个启动类,SpringBoot就启动成功了,并且帮我们配置了好多自动配置类. 其中最重要是 @Spring

IDEA+SpringBoot MyBatis Dynamic SQL的初体验(一)

ybatis generator在2017年12月发布了version 1.3.6,在该版本添加了新的TargetRuntime: MyBatis Dynamic SQL(mybatis 动态SQL)    Mybatis Dynamic Sql与以前TargetRuntime相比较: 移除了XXXExamle类和xml文件,代价是不兼容其他的TargetRuntime java版本限制,生成器将需要运行Java 8,低版本可能会出现错误 代码逻辑相对以前,使用了 lambda表达式,是的较容易

springboot+支付宝完成秒杀项目的初体验

springboot+支付宝完成秒杀项目的初体验 思考的问题: 首先是秒杀的商品查询,考虑到是热点数据,所以写一个接口读取当日批次的秒杀商品到redis中(那么接下来对商品的操作都放入redis中). 当用户抢购商品时,考虑到的是是否在秒杀时间段内以及商品是抢完的问题.首先需要判断该商品是否在秒杀时间内,然后要查询该商品数量是否足够.当然这些还不够,还要有为了防止高并发的解决方案: 对用户限流:对恶意请求通过ip设置访问次数,超过次数则抛出异常. 利用消息队列的异步请求来削峰. 利用redis做

第66讲:Scala并发编程实战初体验及其在Spark源码中的应用解析

王家林亲授<DT大数据梦工厂>大数据实战视频“Scala深入浅出实战经典”视频.音频和PPT下载!第66讲:Scala并发编程实战初体验及其在Spark源码中的应用解析百度云:http://pan.baidu.com/s/1pJ5jzHx腾讯微云:http://url.cn/aSawrm360云盘:http://yunpan.cn/cctL3QYACaVNa  访问密码 c0fb 信息来源于 DT大数据梦工厂微信公众账号:DT_Spark