SpringBoot自动装配原理及快速上手

一、什么是SpringBoot ?

SpringBoot就是一个javaweb框架,和springmvc类似,官方的说法是简化开发、约定大于配置。SpringBoot最大的特点就是:自动装配

为什么要有springboot?它帮我们解决了什么问题?

众所周知,Spring是一个开源框架,从2003年兴起,随着Spring的不断发展,涉及的领域越来越多,项目整合开发需要配置各种各样的文件,配置过程十分繁琐,使得spring的使用变得困难起来。SpringBoot就是在这样的一个背景下被抽象出来的一个开发框架,目的就是为了让大家更容易的使用Spring,更容易的集成其他中间件、软件等。

注意:
SpringBoot本身不提供Spring的核心特性,它不是什么新框架(其实我觉得可以理解成springboot是对spring的再一次封装,使我们用起来更加方便)。
SpringBoot以约定大于配置的核心思想,默认帮我们进行了很多的配置,使我们编写很少的配置信息,或甚至不用配置任何东西直接将依赖导入就能用(这就是springboot的开箱即用)。

SpringBoot的主要优点:

1.为所有Spring开发者更快的入门

2.开箱即用,提供各种默认配置来简化项目配置

3.内嵌式容器简化Web项目

4.没有冗余代码生成和XML配置的要求

二、SpringBoot自动装配原理解析

2.1 pom文件解析

首先我们从pom.xml文件开始来解析,在SpringBoot项目中,pom文件中主要导入了一个parent父项目依赖:

 <parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.0.3.RELEASE</version>
</parent>

点进去后会发现还有一个parent父项目依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
</parent>

以上这个依赖就是SpringBoot项目中的版本控制中心,之后我们在pom文件中导入依赖默认就无需再写版本号了,除非导入的包不在上面的依赖管理中,就要指定版本。

启动器starter:
SpringBoot项目的pom文件中还有很多类似如下的启动器:

<dependency>  
	<groupId>org.springframework.boot</groupId>  
 	<artifactId>spring-boot-starter-web</artifactId>  
</dependency>  
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

启动器的作用就是把我们需要的功能制作成一个个的启动器,我们需要什么功能就把相应的启动器导入进去,springboot就会帮我们导入该功能所需要的所有依赖。(比如web启动器,导入后它就会帮我们导入web环境所需的所有依赖,redis启动器,帮我们导入redis所需的所有依赖。感觉其实就像是对某些功能的封装,然后我们导入对应的starter就能用了)

2.2 SpringBoot主程序解析

@SpringBootApplication // 此注解的意思是标注此类是一个SpringBoot应用
public class SpringbootbuildApplication {

	public static void main(String[] args) {
	    // 启动springBoot
		SpringApplication.run(SpringbootbuildApplication.class, args);
	}

}

从上面的方法来看,springboot的所有特性和原理应该都藏在@SpringBootApplication此注解和run()方法中,那么我们分别来解析:

2.2.1 @SpringBootApplication注解解析:
此注解点进去后会发现还有多个注解,其中有如下几个:
A. @ComponentScan:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中

B. @SpringBootConfiguration:此注解表明该类这是一个springboot的配置类
这个注解接着点进去后会发现主要还有:

  1. @Configuration:表明当前类是个配置类
  2. @Component:将此类实例化放入ioc容器中(这就表明启动类本身也是一个Spring的组件,负责启动应用)

C. @EnableAutoConfiguration:开启自动配置功能
这个注解就是SpringBoot可以实现自动配置的关键所在!接着点进去这个注解分析里面的内容:

  1. @AutoConfigurationPackage,自动配置包,此注解里面还有@Import({Registrar.class}),import注解的意思是给spring容器中导入一个组件,导入Registrar.class的作用就是:扫描主启动类所在包以及包里面所有的组件到Spring容器中。(所以这个@AutoConfigurationPackage注解就可以理解为扫描组件到容器中的意思(注意:这里扫描的主要是我们自己代码所在的包))
  2. @Import({AutoConfigurationImportSelector.class}):
    AutoConfigurationImportSelector 这个类的作用是:自动配置导入选择器(这个也是把一些组件扫描到ioc容器中,和上面Registrar.class不同的是,这个主要扫描的是springboot写好的一些配置类)。
  3. 从这个AutoConfigurationImportSelector 类的源码分析下去会发现有个spring.factories这个文件一直在出现,它就是自动配置的根源所在
    spring.factories这个配置文件有很多,每一个里面又标注了很多的配置类(这些配置类基本都在 org.springframework.boot.autoconfigure包下),通过反射实例化把这些配置类加载到IOC容器中,由此就实现了自动配置!

SpringBoot帮我们写了这么多的配置类,那这些配置类是怎么写的?又是在何时会生效呢?
下面以HttpEncodingAutoConfiguration这个配置类为例来解析:
首先这个类下有如下注释:

@Configuration // 表明这是一个配置类
// 这个注解就是启动后面()里面指定类的配置功能
//例如这个HttpEncodingProperties.class,像这种xxxProperties这种属性类会自动去读取我们写的配置文件(.yaml\.properties),把我们写的配置属性封装到这个属性类中,
//然后再把这个属性类放到spring容器中
@EnableConfigurationProperties({HttpEncodingProperties.class})
// @Conditional是Spring底层的一个注解,它一般用来判断一种条件,可以理解为if(),满足对应的条件则当前配置类生效,比如下面这个就是判断当前应用是否是web应用
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
// 判断当前项目中是否有CharacterEncodingFilter这个类
@ConditionalOnClass({CharacterEncodingFilter.class})
// 判断当前项目配置文件中是否存在()里的某个配置
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)

所以,SpringBoot给我们提供的这些配置类就是根据不同的条件(@ConditionalOnxxx)来判断当前配置类是否生效

2.3 SpringApplication.run() 方法原理解析:
主程序中的run方法它实际上是开启了一个服务(run方法的解析要比上面注解的更复杂,大致记住以下几点吧),它主要做了以下几件事

  1. 推断当前应用类型是普通项目还是web项目
  2. 查找并加载所有的可用初始化器,设置到initializers属性中
  3. 查找出所有的监听器,设置到listeners属性中
  4. 推断并设置main方法的定义类,找到运行的主类

如果要了解run方法详细的底层原理,可以跟着下图的流程+源码来解析
在这里插入图片描述

2.4 SpringBoot自动装配原理总结

  1. springboot项目的pom文件中有个父依赖spring-boot-dependencies,在这里管理了boot项目中所有的依赖版本,所以我们导入依赖坐标时一般不用写版本号。
  2. pom文件中有很多功能性的启动器starter,我们需要什么功能就导入对应的启动器即可
  3. springboot项目在启动时会从类路径下读取所有的spring.factories配置文件,并将spring.factories其中对应的配置类(这些自动配置类都在org.springframework.boot.autoconfigure下)实例化到IOC容器中,以此来实现自动配置。
  4. 这些自动配置类(xxxAutoConfigurartion)根据**@Conditional注解来判断何时生效**,通过读取xxxProperties属性类(属性类会自动将我们写的配置属性如端口号,数据库连接信息等封装进去)来设置配置属性。然后将这些自动配置类放入IOC容器中,也就完成了springboot的自动配置。

三、IDEA快速创建springboot项目

  1. spring官方给我们提供了一个springboot项目模板,用idea可以快速创建
    在这里插入图片描述
  2. 输入gav,选择java版本
    3.
  3. 选择需要的导入模板,比如web项目,lombok,thymeleaf模板引擎在这里插入图片描述
    然后finshed就完成了

四、SpringBoot整合其他技术框架

由于springboot自动装配的特点,在整合其他技术及框架时基本达到了开箱即用的效果,基本都是导入依赖再加上一些极少甚至不用加的一些配置信息即可。(这里的整合是按步骤来的,数据源、mybatis、mvc)

  1. springboot整合jdbc
    导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

在application.yaml配置文件中编写数据库连接信息

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver

以上两步即可,需要注意的是,springboot默认给我们导入的数据源(数据源就是数据库连接信息存放的地方,也可使说就是数据库连接池,有了数据源我们就可以操作数据库了)是HikariDataSource ,这个数据源号称是javaweb当前最快的数据源。

  1. springboot整合druid
    导入druid数据源依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.21</version>
</dependency>

springboot因为默认使用hikari数据源,我们要切换成druid数据源只需要在配置文件中指定数据源的type即可

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源(在这里指定数据源使用哪个)
	
	#Spring Boot 默认是不注入这些属性值的,需要自己绑定
	#(绑定的方法就是我们要自己写一个数据源的配置类,把下面这些配置和数据源DruidSource绑定到一起,然后再把DruidSource注入到ioc容器中)
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

下面我们自己来写一个关于druid数据源的配置类

@Configuration // 标明这是一个配置类
public class DruidConfig {

    
    @ConfigurationProperties(prefix = "spring.datasource")// 读取配置文件中我们自己写的配置信息,并将这些属性值注入到DruidDataSource中
    @Bean // 将DruidDataSource数据源添加的容器中,不再让springgboot自动创建(因为我们要使用druid数据源专有的属性)
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

}

Druid还具有数据监控功能,并且自带web界面方便用户查看。但是在使用之前我们还是要进行一定的配置(这是一些固定的配置不用记,需要的时候拿来用即可):

//配置 Druid 监控管理后台的Servlet;
//内置 Servlet 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
@Bean
public ServletRegistrationBean statViewServlet() {
    ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
	
	// 创建一个map,里面存放一些所需的键值对属性
    Map<String, String> initParams = new HashMap<>();
    // 设置登录的用户名和密码,这里的key是固定的
    initParams.put("loginUsername", "admin"); 
    initParams.put("loginPassword", "123456"); 

    //后台允许谁可以访问
    //initParams.put("allow", "localhost"):表示只有本机可以访问
    //initParams.put("allow", ""):为空或者为null时,表示允许所有访问
    initParams.put("allow", "");
    //deny:Druid 后台拒绝谁访问 
    //initParams.put("hhl", "192.168.1.63");表示禁止此ip访问

    //设置初始化参数
    bean.setInitParameters(initParams);
    return bean;
}


//配置 Druid 监控 之  web 监控的 filter
//WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
@Bean
public FilterRegistrationBean webStatFilter() {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(new WebStatFilter());

    //exclusions:设置哪些请求进行过滤排除掉,从而不进行统计
    Map<String, String> initParams = new HashMap<>();
    initParams.put("exclusions", "*.js,*.css,/druid/*,/jdbc/*");
    bean.setInitParameters(initParams);

    //"/*" 表示过滤所有请求
    bean.setUrlPatterns(Arrays.asList("/*"));
    return bean;
}

  1. springboot整合mybatis
    导入mybatis依赖(下面这个依赖是mybatis研发的,不是boot哦~)
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.1</version>
</dependency>

数据源已经在第2点配置过了,再进行些简单的配置即可

mybatis:
	type-aliases-package: com.hhl.pojo # 给此包下的javabean配置别名,默认类名首字母小写
	mapper-locations: classpath:mybatis/mapper/*.xml # 扫描此路径下存放sql的xml文件

编写xxxdao

@Mapper // 此注解的作用其实就是生成一个该接口的实现类,和SSM整合里面MapperScannerConfigurer的作用差不多
@Repository
public interface DepartmentMapper {

    // 获取所有部门信息
    List<Department> getDepartments();

    // 通过id获得部门
    Department getDepartment(Integer id);

}

编写xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.kuang.mapper.DepartmentMapper">
	<select id="getDepartments" resultType="Department">
       select * from department;
    </select>
</mapper>

mybatis的整合基本达到了开箱即用,导入依赖、配置下别名和扫描的xml包就可以用了!

  1. web静态资源处理及mvc自动配置扩展
    根据boot源码可以得出以下结论,springboot项目中在以下路径下的资源可自动被识别为静态资源(classpath是指根目录,创建项目时那个java、resource包就是根目录):
    “classpath:/META-INF/resources/”
    “classpath:/resources/”
    “classpath:/static/”
    “classpath:/public/”
    上面是boot默认的存放静态资源的地方,当然我们还可以自定义存放静态资源的路径:
    (不配置静态资源过滤的话,jsp访问项目中的静态资源就会访问不到)
spring: # 注意:当你自定义静态资源路径后,上面的boot自动配置的默认静态资源路径就会失效了
	resources:
		static-locations: classpath:/jingtai/, classpath:/hhl/

mvc自动配置类:WebMvcAutoConfiguration ,这是boot提供的。

spring:
	mvc:
		view: # 配置视图解析器的前缀和后缀
			prefix: /templates/
			suffix: .html 

我们也可以自己写一个自定义的mvc配置类,实现WebMvcConfigurer接口。
@EnableWebMvc:此注解放到我们自己的mvc配置类上时,就表明我们自己全面接管mvc的配置,不需要springboot的mvc自动配置功能了。(这个一般不用,了解即可)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值