草庐IT

springBoot自动装配

嘴强程序员 2023-07-23 原文

目录

1. 作用

2. 注解

 2.1 元注解

2.2 @Import

2.3 @Configuration

2.4 @ConditionalXXX

2.5 EnableConfigurationProperties

3. 配置文件

4. 结构

4.1 启动器

4.2 自动配置

5. 开发示例

5.1 创建工程

5.2 创建模块

 5.3 开发自动配置模块

5.3.1 HelloProperties

 5.3.2 IHelloService

5.3.3 HelloService

5.3.4 HelloServiceAutoConfigration

5.3.5 spring.factories

​编辑

 5.3.6 安装到本地仓库

6. 使用自动装配模块


1. 作用

为了简化配置,使spring的使用更加方便,例如:可以回忆一下springboot中是如何继承redis的。

spring配置方式的进化过程:

  • xml的方式配置
  • java config的方式配置,使用@configuration注解在java中配置
  • 自动装配

springboot starter作用:

  • 引入模块所需的相关jar包
  • 自动配置各自模块所需的属性

使用springboot后集成常用的第三方框架变得非常简单了。

springboot starter带来的问题
starter使SpringBoot集成第三方框架变得简单,但对刚刚上手SpringBoot的人来说,可能只知道配置属性是在application.xml或application.yml中添加,但他们各自的属性都有哪些,具体怎么配置,却无从下手

2. 注解

自动装配相关的注解示例: 

 2.1 元注解

为更好的理解装配过程,复习一下元注解。

  • @Target: 自定义注解的使用范围,比如类,方法,属性等
  • @Retention: 保留策略,如源码中保存(@Override),class中保存(@SupperWarning),运行时保存等
  • @Docmented: 为javadoc使用的。
  • @Inherited: 被其修饰的自定义注解可以被子类继承

2.2 @Import

作用:为容器导入bean的定义
常用的三种方式:
1) @Import(value={A.class}) 将A类导入容器中,交给IOC管理
2) @Import(value={XxxImportBeanDefinitionRegister.class}) 也是将bean导入容器中,与上面不同的是实现了ImportBeanDefinitionRegistrar接口,该接口用来动态注册bean
3) @Import(value={XxxImportSelector.class}) 可以批量导入,需要实现ImportSelector接口,该接口返回一个数组(需要注册的bean的全路径),实现批量注册。

2.3 @Configuration

被挂上@Configuration注解,表明它是一个配置类,作用等同于xml配置,里面有被@Bean注解的方法,也等同于xml配置的各种<bean>

2.4 @ConditionalXXX

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

2.5 EnableConfigurationProperties

作用就是将@ConfigurationProperties修饰的Bean加入到IOC容器中。@ConfigurationProperties与@EnableConfigurationProperties注解结合,可以方便的读取配置文件。

3. 配置文件

META-INF/spring.factories

如:

4. 结构

4.1 启动器

一个空的jar包,提供依赖管理。这些依赖可能用于自动装配或其他的第三方jar

命名规范

  • spring官方的start: spring-boot-starter-xxx
  • 自定义的start: xxx-spring-boot-starter

4.2 自动配置

编写一个自动配置的模块,用于完成自动配置, 上一步的启动器依赖于自动配置, 用户在使用时自需引入启动器模块,即可自动导入自动配置模块。

5. 开发示例

5.1 创建工程

创建一个空工程,在该工程中创建两个模块,一个为start模块(启动类),一个为自动配置模块。

创建一个名为:springbootstartdemo的空项目

 创建空目录后创建两个项目模块 demo-spring-boot-starter 与  demo-spring-boot-starter-autoconfigurer

1.创建好空目录后👇 进入项目设置 

2.创建两个maven项目普通项目即可

5.2 创建模块

启动模块只需要导入自动配置模块,所以不需要集成springboot父项目。 自动配置模块需要依赖一spring-boot-start(Spring Boot核心starter,包含自动配置、日志、yal配置文件支持),所以需要spring-boot-starter-parent为父项目。

一个为start模块,启动模块,不需要做任何开发,只用在pom.xml配置文件中导入自动配置模块。使用者通过导入启动模块,启动模块导入自动配置模块,(可以将start启动模块想象成使用导火索)

请注意上面提到的命名规范。

 自动配置模块

 5.3 开发自动配置模块

启动类的作用是导入自动配置模块,并不要进行编码开发

在自动配置模块如下:

5.3.1 HelloProperties

该类的作用时读取项目的配置文件, 使用@ConfigurationProperties注解,并指定读取demo.starter前缀的配置文件。

@ConfigurationProperties(prefix = "demo.starter")
public class HelloProperties {

    //greeting问候
    private String greeting;

    public String getGreeting() {
        return greeting;
    }

    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }

 5.3.2 IHelloService

定义的接口

package com.zking.boot;

public interface IHelloService {
    String sayHello(String name);
}

5.3.3 HelloService

该类用于通过传入的参数,与配置文件中的配置,组成一个字符串返回, 没有业务意义,仅用于演示spring start的运行原理。

public class HelloService implements IHelloService {

    HelloProperties helloProperties;

    public HelloProperties getHelloProperties() {
        return helloProperties;
    }

    public void setHelloProperties(HelloProperties helloProperties) {
        this.helloProperties = helloProperties;
    }

    @Override
    public String sayHello(String name) {
        return helloProperties.getGreeting() + " " + name;
    }
}

5.3.4 HelloServiceAutoConfigration

该类用于进行自动配置

@Configuration  //表明该类为配置类
@ConditionalOnWebApplication  //指定该配置类在web环境下有效
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfigration {

    @Autowired
    HelloProperties helloProperties;

    @Bean
    public IHelloService helloService() {
        HelloService helloService = new HelloService();
        helloService.setHelloProperties(helloProperties);
        return helloService;
    }

}

5.3.5 spring.factories

编写spring.factories, 可以参mybatis-spring-boot-autoconfigure编写

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

具体配置

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.lisen.starter.HelloServiceAutoConfigration

 5.3.6 安装到本地仓库

 将工程安装到本地仓库,以便于其他的工程使用。

因为启动模块需要依赖与自动配置模块,所以先安装自动配置模块,再安装启动模块。

到此为止一个自动装配模块就开发完成,下面看看如何使用。

6. 使用自动装配模块

创建一个springboot项目,并在pom.xml中引入上面的自动配置模块(只需引入启动类,启动类自动引入配置模块)。

 pom.xml

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


    <properties>
        <java.version>1.8</java.version>
        <mysql.driver.version>5.1.44</mysql.driver.version>
    </properties>

    <dependencies>

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

        <dependency>
            <groupId>org.lisen.starter</groupId>
            <artifactId>demo-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

项目配置文件: application.properties

server.port=8080
server.servlet.context-path=/
server.tomcat.uri-encoding=utf-8

demo.starter.greeting=hello

启动类:

@SpringBootApplication
public class AppStarter {

    public static void main(String[] args) {

        SpringApplication.run(AppStarter.class, args);

    }

}

controller

@RestController
public class HelloController {

    @Autowired
    private IHelloService helloService;

    @RequestMapping("/hello")
    public String hello() {
        return helloService.sayHello("zs");
    }

}

最后启动服务,调用http://localhost:8080/hello,如果提示信息正常输出则说明运行成功。

有关springBoot自动装配的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  4. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  5. ruby - 在 ruby​​ 中使用自动创建插入数组 - 2

    我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?

  6. 【自动驾驶环境感知项目】——基于Paddle3D的点云障碍物检测 - 2

    文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3

  7. ruby-on-rails - 自动完成搜索的 Rails 实现 - 2

    我不确定如何为我的搜索功能添加自动完成表单。"get"do%>nil%>我有一个具有自定义操作的Controllerdefquery@users=Search.user(params[:query])@article=Search.article(params[:query])end模型如下:defself.user(search)ifsearchUser.find(:all,:conditions=>['first_nameLIKE?',"%#{search}%"])elseUser.find(:all)endenddefself.article(search)ifsearchArt

  8. ruby - 如何设置自动测试以仅重新运行失败的 rspec 示例 - 2

    我对自动测试的工作方式的印象(基于cucumbergithubwiki和其他在线内容)是它应该重新运行红色示例,直到它们通过。我的问题是它会重新运行规范文件中找到失败示例的所有示例,包括通过的示例。我不想浪费时间在修复失败示例的同时重新运行通过的示例。是否可以配置自动测试以便仅运行失败的示例? 最佳答案 您需要rspec-retrygem。以下是文档中有关如何实现它的一些示例:将它应用到覆盖整个测试套件的configureblock中...RSpec.configuredo|config|config.verbose_retry=t

  9. ruby - 在多个线程中引用类方法会导致自动加载循环依赖崩溃 - 2

    代码:threads=[]Thread.abort_on_exception=truebegin#throwexceptionsinthreadssowecanseethemthreadseputs"EXCEPTION:#{e.inspect}"puts"MESSAGE:#{e.message}"end崩溃:.rvm/gems/ruby-2.1.3@req/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:478:inload_missing_constant':自动加载常量MyClass时检测到循环依赖稍加研究后,

  10. ruby - 自动将院子文档框架添加到现有的 Rails 遗留代码中 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭4年前。Improvethisquestion我希望能够将模板化的YARD文档样式注释插入到我现有的Rails遗留应用程序中。目前它的评论很少。我想要具有指定参数的类header和方法header(通过从我假定的方法签名中提取)和返回值的占位符。在PHP代码中,我有一些工具可以检查代码并在适当的位置创建插入到代码中的文档header注释。在带有Ducktyping等的Ruby中,我确信诸如@params等类型之类

随机推荐