分开描述各自的特征:
Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都是Spring 的ioc和 aop,ioc 提供了依赖注入的容器, aop解决了面向横切面的编程,而后在此二者的基础上实现了其余延伸产品的高级功能。css
Spring MVC提供了一种轻度耦合的方式来开发web应用。它是Spring的一个模块,是一个web框架。经过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易。解决的问题领域是网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。web
Spring Boot实现了自动配置,下降了项目搭建的复杂度。它主要是为了解决使用Spring框架须要进行大量的配置太麻烦的问题,因此它并非用来替代Spring的解决方案,而是和Spring框架紧密结合用于提高Spring开发者体验的工具。同时它集成了大量经常使用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎能够零配置的开箱即用(out-of-the-box)。面试
因此,用最简练的语言归纳就是:
Spring 是一个“引擎”;
Spring MVC 是基于Spring的一个 MVC 框架;
Spring Boot 是基于Spring4的条件注册的一套快速开发整合包。 spring
从代码里看项目SpringBoot的项目启动类只有一个注解@SpringBootApplication和一个run方法。sql
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
复制代码
直接看@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 { @AliasFor( annotation = EnableAutoConfiguration.class ) Class<?>[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class ) String[] excludeName() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackages" ) String[] scanBasePackages() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackageClasses" ) Class<?>[] scanBasePackageClasses() default {}; } 复制代码
@SpringBootApplication:包含了@SpringBootConfiguration(打开是@Configuration),@EnableAutoConfiguration,@ComponentScan注解。编程
JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,因此,这里的启动类标注了@Configuration以后,自己其实也是一个IoC容器的配置类。
对比一下传统XML方式和config配置方式的区别:springboot
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd "> <bean id="app" class="com..." /> 复制代码
@Configuration public class DruidConfiguration { @Bean public FilterRegistrationBean statFilter(){ //建立过滤器 FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter()); //设置过滤器过滤路径 filterRegistrationBean.addUrlPatterns("/*"); //忽略过滤的形式 filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean; } } 复制代码
任何一个标注了@Configuration的Java类定义都是一个JavaConfig配置类。
任何一个标注了@Bean的方法,其返回值将做为一个bean定义注册到Spring的IoC容器,方法名将默认成该bean定义的id。bash
@ComponentScan对应XML配置中的元素,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(好比@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。
咱们能够经过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,若是不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。
注:因此SpringBoot的启动类最好是放在root package下,由于默认不指定basePackages。
markdown
(核心内容)看英文意思就是自动配置,归纳一下就是,借助@Import的帮助,将全部符合自动配置条件的bean定义加载到IoC容器。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; } 复制代码
里面最关键的是@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration能够帮助SpringBoot应用将全部符合条件的@Configuration配置都加载到当前SpringBoot建立并使用的IoC容器。该配置模块的主要使用到了SpringFactoriesLoader。
SpringFactoriesLoader为Spring工厂加载器,该对象提供了loadFactoryNames方法,入参为factoryClass和classLoader即须要传入工厂类名称和对应的类加载器,方法会根据指定的classLoader,加载该类加器搜索路径下的指定文件,即spring.factories文件,传入的工厂类为接口,而文件中对应的类则是接口的实现类,或最终做为实现类。
public abstract class SpringFactoriesLoader {
//...
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
...
}
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
....
}
}
复制代码
因此文件中通常为以下图这种一对多的类名集合,获取到这些实现类的类名后,loadFactoryNames方法返回类名集合,方法调用方获得这些集合后,再经过反射获取这些类的类对象、构造方法,最终生成实例。
继续上面讲的AutoConfigurationImportSelector.class。该类主要关注selectImports方法
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return StringUtils.toStringArray(configurations); } } 复制代码
该方法在springboot启动流程——bean实例化前被执行,返回要实例化的类信息列表。若是获取到类信息,spring能够经过类加载器将类加载到jvm中,如今咱们已经经过spring-boot的starter依赖方式依赖了咱们须要的组件,那么这些组件的类信息在select方法中就能够被获取到。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations; } 复制代码
方法中的getCandidateConfigurations方法,其返回一个自动配置类的类名列表,方法调用了loadFactoryNames方法,查看该方法
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); } 复制代码
自动配置器会跟根据传入的factoryClass.getName()到项目系统路径下全部的spring.factories文件中找到相应的key,从而加载里面的类。咱们就选取这个mybatis-spring-boot-autoconfigure下的spring.factories文件
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 复制代码
进入org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration中,又是一堆注解
@org.springframework.context.annotation.Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnBean({DataSource.class})
@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class MybatisAutoConfiguration
{
private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);
private final MybatisProperties properties;
private final Interceptor[] interceptors;
private final ResourceLoader resourceLoader;
private final DatabaseIdProvider databaseIdProvider;
private final List<ConfigurationCustomizer> configurationCustomizers;
复制代码
@Spring的Configuration是一个经过注解标注的springBean,
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class})这个注解的意思是:当存在SqlSessionFactory.class, SqlSessionFactoryBean.class这两个类时才解析MybatisAutoConfiguration配置类,不然不解析这一个配置类。咱们须要mybatis为咱们返回会话对象,就必须有会话工厂相关类
@CondtionalOnBean(DataSource.class):只有处理已经被声明为bean的dataSource
@ConditionalOnMissingBean(MapperFactoryBean.class)这个注解的意思是若是容器中不存在name指定的bean则建立bean注入,不然不执行
以上配置能够保证sqlSessionFactory、sqlSessionTemplate、dataSource等mybatis所需的组件都可被自动配置,@Configuration注解已经提供了Spring的上下文环境,因此以上组件的配置方式与Spring启动时经过mybatis.xml文件进行配置起到一个效果。
只要一个基于SpringBoot项目的类路径下存在SqlSessionFactory.class, SqlSessionFactoryBean.class,而且容器中已经注册了dataSourceBean,就能够触发自动化配置,意思说咱们只要在maven的项目中加入了mybatis所须要的若干依赖,就能够触发自动配置,但引入mybatis原生依赖的话,每集成一个功能都要去修改其自动化配置类,那就得不到开箱即用的效果了。因此Spring-boot为咱们提供了统一的starter能够直接配置好相关的类,触发自动配置所需的依赖(mybatis)以下:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
复制代码
由于maven依赖的传递性,咱们只要依赖starter就能够依赖到全部须要自动配置的类,实现开箱即用的功能。也体现出Springboot简化了Spring框架带来的大量XML配置以及复杂的依赖管理,让开发人员能够更加关注业务逻辑的开发。
最后再亲情分享一个本身感受比较好的用来导出数据库表结构的软件,连接七天有效 连接:https://pan.baidu.com/s/1-r9pP9VV3Rws6B8mV-bBMw 密码:bfy7