Spring Boot(04)——创建自己的自动配置

简介:

创建自己的自动配置

当你的应用需要以jar包的形式提供给其它应用使用时,可以考虑把它们封装为一个Spring Boot Starter。即该jar包是可以自动添加需要引用的依赖项,也能够对核心功能进行自动配置。自动配置的核心类是一个标注了@Configuration的类,然后在自动配置类中可以定义相应的bean。比如下面的配置类中定义了一个HelloBean类型的bean。

@Configuration
public class HelloAutoConfiguration {

    @Bean
    public HelloBean helloBean() {
        return new HelloBean();
    }
    
}

然后需要在Classpath下的META-INF/spring.factories中以org.springframework.boot.autoconfigure.EnableAutoConfiguration为Key,以对应的自动配置类为Value进行配置,如果有多个自动配置类,多个自动配置类之间可以以英文逗号分隔。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.elim.autoconfigure.HelloAutoConfiguration

Spring Boot在启动时将读取Classpath下META-INF/spring.factories中Key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置类,将它们进行实例化。所以经过上述配置后,系统启动后将自动创建HelloBean类型的bean。

自动配置类通常不会像上面那样直接进行定义,而是会添加一些附加条件,比如在Classpath中拥有某些Class才生效,或者需要bean容器中不存在指定bean时才生效等等。Spring Boot为它们提供了一系列的@ConditionalXXX,常用的如下:

  • ConditionalOnClass :用于指定在Classpath下拥有某些Class时才生效
  • ConditionalOnMissingClass :用于指定在Classpath下不存在某些Class时才生效
  • ConditionalOnBean :用于指定在bean容器中存在某些bean时生效
  • ConditionalOnMissingBean :用于指定在bean容器中不存在某些bean时生效
  • ConditionalOnWebApplication :用于指定当应用是Web应用时生效
  • ConditionalOnNotWebApplication :用于指定当应用是非Web应用时生效
  • ConditionalOnProperty :用于指定当配置了某些特定的参数时生效
  • ConditionalOnExpression :用于根据SpEl表达式控制是否生效
  • ConditionalOnSingleCandidate :用于指定当bean容器中只存在唯一的指定类型的bean时才生效;当bean容器中存在多个指定类型的bean,但是使用@Primary指定了主候选者也是可以匹配的,即也是生效的

更多可用的Conditional注解可以参考API文档的org.springframework.boot.autoconfigure.condition包。

下面的代码中指定了当Classpath下存在Hello.class,且bean容器中不存在HelloBean类型的bean时下面的配置类将生效。

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {

    @Bean
    public HelloBean helloBean() {
        return new HelloBean();
    }
    
}

这些条件配置注解也是可以添加到bean上的。比如下面代码中指定了当Environment中存在Key为autoconfigure.hello.enabled属性且其值为true时将创建HelloBean类型的bean,或者当Environment中不存在Key为autoconfigure.hello.enabled属性时也将创建HelloBean类型的bean(由matchIfMissing控制)。所以针对下面的配置,默认情况下是会创建HelloBean类型的bean的,如果不期望创建该类型的bean,可以在application.properties文件中指定autoconfigure.hello.enabled=false

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {

    @Bean
    @ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", havingValue = "true", matchIfMissing = true)
    public HelloBean helloBean() {
        return new HelloBean();
    }

}

当使用@ConditionalOnProperty时如果对应的值的可选值是true/false,可以不指定havingValue属性,此时只要值不为false,都会认为是true。

绑定参数

通常自定义的Starter会需要依靠外部配置的属性进行一些自动配置。此时可以使用@ConfigurationProperties标注在用来接收属性的Class上,它可以指定一个前缀,然后将在application.properties中寻找指定前缀和字段名称组合起来的属性进行绑定。比如下面的属性类中的name属性将绑定application.properties中定义的autoconfigure.hello.name属性的值。

@Data
@ConfigurationProperties("autoconfigure.hello")
public class HelloProperties {

    private String name;
    
    private String message;
    
}

@ConfigurationProperties标注的Class需要通过在配置类上使用@EnableConfigurationProperties进行启用。@EnableConfigurationProperties指定的配置类会自动注册为Spring bean容器中的一个bean,然后可以在配置类中自动注入对应的属性类。比如下面的代码中在HelloAutoConfiguration类上通过@EnableConfigurationProperties(HelloProperties.class)指定了启用HelloProperties这个属性配置类,然后把它定义为HelloAutoConfiguration类中的一个属性,并标注为自动注入,然后在定义HelloBean类型的bean时从HelloProperties中获取属性值进行配置。

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {

    @Autowired
    private HelloProperties helloProperties;
    
    @Bean
    @ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", matchIfMissing = true)
    public HelloBean helloBean() {
        HelloBean helloBean = new HelloBean();
        helloBean.setName(helloProperties.getName());
        return helloBean;
    }

}

上面的代码中定义HelloBean时从HelloProperties中获取name属性赋值给了HelloBean对象的name属性。这样的需求其实可以直接通过@ConfigurationProperties给HelloBean的name属性赋值,而不必添加多余的HelloProperties类。把@ConfigurationProperties定义在HelloBean定义的方法上可以拥有相同的效果,比如下面这样。

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {

    @Bean
    @ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", matchIfMissing = true)
    @ConfigurationProperties("autoconfigure.hello")
    public HelloBean helloBean() {
        return new HelloBean();
    }

}

使用@ConfigurationProperties定义属性配置类时最好定义的前缀不要以spring开头,以免跟未来Spring官方提供的属性配置类存在冲突。

自定义的Starter在命名时不要命名为spring-boot-starter-xxx,可以命名为xxx-spring-boot-starterspring-boot-starter-xxx留给官方使用。

参考文档

https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/html/boot-features-developing-auto-configuration.html

(注:本文基于Spring Boot 2.0.3所写)

目录
相关文章
|
8天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
28 0
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
42 4
|
1月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
37 0
|
25天前
|
Java API Spring
在 Spring 配置文件中配置 Filter 的步骤
【10月更文挑战第21天】在 Spring 配置文件中配置 Filter 是实现请求过滤的重要手段。通过合理的配置,可以灵活地对请求进行处理,满足各种应用需求。还可以根据具体的项目要求和实际情况,进一步深入研究和优化 Filter 的配置,以提高应用的性能和安全性。
|
8天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
20 2
|
17天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
28 1
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
54 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
1月前
|
Java BI 调度
Java Spring的定时任务的配置和使用
遵循上述步骤,你就可以在Spring应用中轻松地配置和使用定时任务,满足各种定时处理需求。
125 1
|
2月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
218 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
1月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
62 2