首页 > 其他分享 >spring-boot-starter

spring-boot-starter

时间:2023-08-22 17:12:24浏览次数:37  
标签:spring boot springframework import org starter

spring boot在配置上相比spring要简单很多,其核心在于spring-boot-starter,在使用spring boot来搭建一个项目时,只需要引入官方提供的starter,就可以直接使用,免去了各种配置。
starter简单来讲就是引入了一些相关依赖和一些初始化的配置

  • 命名规范:
    • 官方的starter: spring-boot-starter-xxx 例如:spring-boot-starter-web
    • 第三方的starter:xxx-spring-boot-starter 例如:mybatis-spring-boot-starter

原理

Spring Boot之所以能够帮我们简化项目的搭建和开发过程,主要基于它提供的起步依赖和自动配置

起步依赖

将具备某种功能的坐标打包到一起,可以简化依赖导入的过程。
例如:mybatis-spring-boot-starter

自动配置

即无须手动配置xml,自动配置并管理bean,可以简化开发过程。

实例分析

Spring boot默认扫描启动类所在的包下的主类与子类的所有组件,但并没有包括依赖包中的类
以mybatis-spring-boot-starter为例分析

起步依赖

  • 在pom文件中,添加坐标
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>1.3.2</version>
</dependency>

SpringBoot是如何知道要加载哪些配置的

最先关注到的是@SpringBootApplication注解

image.png

进入到@SpringBootApplication注解内部

  • @SpringBootConfiguration:标识这个一个配置类,内部实际是一个@Configuration
  • @EnableAutoConfiguration:表示启用自动配置

image.png

进入到@EnableAutoConfiguration注解内部:

  • @Import:将类交给spring容器管理

image.png

进入AutoConfigurationImportSelector对象内部

  • getCandidateConfiguration:获取待加载的配置类,读取各starter的META_INF/spring.factory中的bean的全类名,用于加载这些bean并完成实例化的创建工作

image.png

Starter内部是如何进行自动配置的

找到mybatis-spring-boot-autoconfigure�中的META_INF/spring.factory

打开META_INF/spring.factory

具体配置的是org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
image.png

进入MybatisAutoConfiguration

  • 通过@Configuration+@Bean注解,将返回的对象交给spring容器管理,用来替代传统的xml配置文件

image.png

自动配置条件依赖

在上面的MybatisAutoConfiguration中看到有很多注解,这些注解的用途如下

注解 用途
@ConditionalOnBean 仅当当前上下文中存在某个bean时,才会实例化这个bean
@ConditionalOnClass 某个class位于类路径上,才会实例化这个bean
@ConditionalOnExpression 当表达式为true的时候,才会实例化这个bean
@ConditionalOnMissingBean 仅在当前上下文中不存在某个bean时,才会实例化这个bean
@ConditionalOnMissingClass 某个class在类路径上不存在时,才会实例化这个bean
@ConditionalOnNotWebApplication 不是web应用时,才会实例化这个Bean
@AutoConfigureAfter 在某个bean完成自动配置后,才会实例化这个Bean
@AutoConfigureBefore 某个bean完成自动配置前,才会实例化这个Bean

如何将一个普通类交给Spring容器管理

  • 使用@Configuration + @Bean注解
  • 使用@Controller、@Service、@Repository、@Component
  • 使用@Import方法

实现

spring-boot-starter是为了在项目初始化的时候,向spring容器中注入一些bean。
这些bean在注入的时候可以读取配置文件,进行动态的调整

案例一

向spring容器中注入一个SimpleService,通过SimpleService读取配置(simple.name/simple.address)

  • 创建一个maven工程,并添加坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--案例1-第一步:引入坐标-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version>
    </parent>

    <groupId>com.tzcxyh</groupId>
    <artifactId>simple-spring-boot-starter</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--案例1-第一步:引入坐标-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
      
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

        <!--对配置生成原数据,写配置文件的时候,会有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>
  • 创建SimpleProperties对象,读取配置
package com.tzcxyh.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
/**
 * @Description 配置属性类,读取配置文件中的参数信息
 **/
@ConfigurationProperties(prefix = "simple")
public class SimpleProperties {

    private String name;
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

  • 创建SimpleService对象,根据配置输出
package com.tzcxyh.service;

/**
 * @Description 服务类
 **/
public class SimpleService {
    private String name;
    private String address;

    public SimpleService(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String sayHello(){
        return "你好!我的名字叫" + this.name + ", 我来自" + this.address;
    }
}

  • 创建SimpleAutoConfiguration,将SimpleService注入到Spring容器中
package com.tzcxyh.config;

import com.tzcxyh.service.SimpleService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description 自动配置类
 * 读取SimpleProperties配置 + 自动配置SimpleService
 **/
@Configuration
//启用SimpleProperties对象,读取配置文件
@EnableConfigurationProperties(SimpleProperties.class)
public class SimpleServiceAutoConfiguration {

    private SimpleProperties simpleProperties;

    /**
     * 以构造函数的方式注入配置
     * @param simpleProperties
     */
    public SimpleServiceAutoConfiguration(SimpleProperties simpleProperties) {
        this.simpleProperties = simpleProperties;
    }

    @Bean//与@Configuration一起,将返回bean交给spring容器管理
    @ConditionalOnMissingBean//外部没有定义的时候才会创建这个bean
    public SimpleService simpleService(){
        return new SimpleService(simpleProperties.getName(), simpleProperties.getAddress());
    }
}

  • 在META-INF/spring.factories中添加SimpleAutoConfiguration全类名
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tzcxyh.config.SimpleServiceAutoConfiguration

案例二

自定义日志注解,通过拦截器的方式,计算方法调用时长。在案例一的基础上添加

  • 创建一个maven工程,并添加坐标
<!--案例2-第一步:引入坐标-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <!--对外隐藏-->
  <optional>true</optional>
</dependency>
  • 创建@SimpleLog注解
package com.tzcxyh.log;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleLog {
    /**
     * 方法描述
     * @return
     */
    String desc() default "";
}
  • 创建SimpleLogInterceptor�对象,继承HandlerInterceptorAdapter�,重写preHandler、postHandler方法
package com.tzcxyh.log;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @Description 日志拦截器
 **/
public class SimpleLogInterceptor extends HandlerInterceptorAdapter {
    /**
     * 存储开始时间的时间戳,用于计算方法调用时间
     */
    private static final ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        SimpleLog simpleLog = method.getAnnotation(SimpleLog.class);
        if(simpleLog != null){
            //存在注释,记录开始时间
            long startTime = System.currentTimeMillis();
            startTimeThreadLocal.set(startTime);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        SimpleLog simpleLog = method.getAnnotation(SimpleLog.class);
        if(simpleLog != null){
            long endTime = System.currentTimeMillis();
            Long startTime = startTimeThreadLocal.get();
            long optTime = endTime - startTime;

            String requestURI = request.getRequestURI();
            String methodName = method.getDeclaringClass().getName() + "." + method.getName();
            String methodDesc = simpleLog.desc();
            System.out.println("请求URI:" + requestURI);
            System.out.println("请求方法名:" + methodName);
            System.out.println("方法描述:" + methodDesc);
            System.out.println("方法执行时间:" + optTime + "ms");
        }
        super.postHandle(request, response, handler, modelAndView);
    }
}
  • 创建SimpleLogAutoConfiguration�,实现WebMvcConfigurer�,将SimpleLogInterceptor加入拦截器中
package com.tzcxyh.config;

import com.tzcxyh.log.SimpleLogInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Description 自动配置类,把SimpleLogInterceptor加入拦截器
 **/
@Configuration
public class SimpleLogAutoConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SimpleLogInterceptor());
    }
}

  • 在META-INF/spring.factories中追加SimpleAutoConfiguration全类名
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.tzcxyh.config.SimpleServiceAutoConfiguration,\
com.tzcxyh.config.SimpleLogAutoConfiguration

测试

将simple-spring-boot-starter打包后,在项目中引入

<dependency>
  <groupId>com.tzcxyh</groupId>
  <artifactId>simple-spring-boot-starter</artifactId>
  <version>1.0.0</version>
</dependency>
  • 添加配置
simple.name=xyh
simple.address=杭州
  • 创建IndexController,测试
package com.tzcxyh.lulu.controller;

import com.tzcxyh.log.SimpleLog;
import com.tzcxyh.service.SimpleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {

    @Autowired
    SimpleService simpleService;

    @GetMapping("/index")
    @SimpleLog(desc = "测试方法")
    public String index(){
        return simpleService.sayHello();
    }
}

  • 访问ip:端口号/index

image.png

  • 控制台输出

image.png

标签:spring,boot,springframework,import,org,starter
From: https://www.cnblogs.com/lulu-buding/p/17649044.html

相关文章

  • SpringCloud
    SpringCloud服务开发注意事项:不同微服务,不开发相同业务2.微服务数据独立,不问其他微服务数据库3.微服务将自己的业务接口暴露为借口,供其他微服务调用提供者与消费者提供者:一次业务中被其他微服务调用的服务(提供接口给其他)消费者:一次业务中调用其他微服务的服务(调用其他......
  • 中小学教育综合管理平台源码,vue2+Java+springboot框架开发
    智慧校园电子班牌软件是出于校园考勤管理以及班级校园信息展示为目的的显示系统软件,电子班牌系统主要用于中小学教育的综合管理平台,融合了多媒体技术、语音技术、人脸识别、信息发布、后台管理等多种技术。智慧班牌通过以云平台为基础,结合互联网、物联网系统进行校园管理,实现学校数......
  • SpringBoot实现统一异常处理
    大家在使用SpringBoot开发项目的时候肯定都需要处理异常吧,没有处理异常那么异常信息直接显示给用户这是非常不雅观的,同时还可能造成用户误会,那么今天我们就来简单的写一下如何在SpringBoot项目中实现统一的异常处理。1.自定义异常类我们先定义一个自定义业务异常类,这个异常类继......
  • 基于springboot课程答疑系统
    随着信息互联网信息的飞速发展,无纸化作业变成了一种趋势,针对这个问题开发一个专门适应师生交流形式的网站。本文介绍了课程答疑系统的开发全过程。通过分析企业对于课程答疑系统的需求,创建了一个计算机管理课程答疑系统的方案。文章介绍了课程答疑系统的系统分析部分,包括可行性分析......
  • 基于springboot师生共评的作业管理系统设计与实现
    随着信息互联网信息的飞速发展,无纸化作业变成了一种趋势,针对这个问题开发一个专门适应师生作业交流形式的网站。本文介绍了师生共评的作业管理系统的开发全过程。通过分析企业对于师生共评的作业管理系统的需求,创建了一个计算机管理师生共评的作业管理系统的方案。文章介绍了师生共......
  • springSecurity异常提示国际化
    1:获取国际化文件在一个jar包里,可以先下载jar包,然后再里面找到中文的那个文件<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-core</artifactId><version>3.2.0.RELEASE</vers......
  • SpringBoot内嵌Tomcat连接池分析
    目录1Tomcat连接池1.1简介1.2架构图1.2.1JDK线程池架构图1.2.2Tomcat线程架构1.3核心参数1.3.1AcceptCount1.3.2MaxConnections1.3.3MinSpareThread/MaxThread1.3.4MaxKeepAliveRequests1.3.5ConnectionTimeout1.3.6KeepAliveTimeout1.4核心内部线程1.4.1Acceptor1.......
  • SpringBoot 测试实践 - 2:单元测试与集成测试
    单元测试vs.集成测试只编写单测,无法测试方法之间的集成情况,而且某些需求可能会修改多个方法,这可能会影响方法对应的单测,涉及到大量的相关单测的修改,这样的维护成本很高可以把重心放在完善集成测试上,专注从外部判断程序是否符合预期。对于一些非常重要的方法,增加单元测试可以减......
  • 搭建SpringCloudAlibaba工程_基于SpringBoot3.+
    打开IDEA新建工程 删除所有文件,仅保留pom.xml,并做出如下修改,可直接复制粘贴,切记调整你为自己项目的groupId和artifactId<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/X......
  • Spring Cloud微服务网关Gateway组件
    网关简介大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去用。  这样的架构,会存在着诸多的问题:每个业务都会需要鉴权、限流、权限校验、跨域等逻......