SpringBoot——自定义自动配置与起步依赖
SpringBoot——自定义自动配置与起步依赖
SpringBoot为我们提供了灵活强大的自动配置与起步依赖功能,接下来我们参考其实现原理,实现专属于我们自己的自动配置与起步依赖。
不仅如此,我们对其稍作修改,让它适用于非SpringBoot环境,甚至是低版本的Spring Framework环境
1自动配置
在编写自己的自动配置之前,我们先来看一下SpringBoot自动配置类的实现原理。
SpringBoot可以根据CLASSPATH、配置项等条件自动进行常规配置,省去了我们自己手动把一模一样的配置复制来复制去的麻烦。这样大大提升了开发效率!
在这之前,我们已经看到过@SpringBootApplication注解了,查看这个注解,可以发现它上面添加了一个@EnableAutoConfiguration,基于这个注解就可以开启自动配置功能。
这两个注解上都有exclude属性,我们可以在其中排除一些不想启用的自动配置类。
如果不想启用自动配置功能,也可以在配置文件中配置spring.boot.enableautoconfiguration=false,关闭该功能。
1.1自动配置的实现原理
自动配置类其实就是添加了@Configuration的普通Java配置类,它利用Spring Framework 4.0加入的条件注解@Conditional来实现“根据特定条件启用相关配置类”,注解中传入的Condition类就是不同条件的判断逻辑。SpringBoot内置了很多条件注解,如下表所示:
条件注解 | 生效条件 |
---|---|
@ConditionalOnBean | 存在特定名称、特定类型、特定泛型参数或带有特定注解的Bean |
@ConditionalOnMissingBean | 与前者相反,不存在特定的Bean |
@ConditionalOnClass | 存在特定的类 |
@ConditionalOnMissingClass | 与前者相反,不存在特定类 |
@ConditionalOnCloudPlatform | 运行在特定的云平台上,截止2.6.3版本,代表云平台的枚举类支持无云平台,可以通过spring.main.cloud-platform配置强制使用的云平台 |
@ConditionalOnExpression | 指定的SpEL表达式为真 |
@ConditionalOnJava | 运行在满足条件的Java上,可以比指定版本新,也可以比指定版本旧 |
@ConditionalOnJndi | 指定的JNDI位置必须存在一个,如没有指定,则需要存在InitalContext |
@ConditionalOnProperty | 属性值满足特定条件,比如给定的属性值都不能为false |
@ConditionalOnResource | 存在特定资源 |
@ConditionalOnSingleCandidate | 当前上下文中,特定类型的Bean有且仅有一个 |
@ConditionalOnWarDeployment | 应用程序是通过传统的War方式部署的,而非内嵌容器 |
@ConditionalOnWebApplication | 应用程序是一个Web应用程序 |
@ConditionalOnNotWebApplication | 与前者相反,应用程序不是一个Web应用程序 |
更多如图所示,就不一一列举了:
以@ConditionalOnClass注解为例,它的定义如下所示,@Target指明该注解可用于类型和方法定义,@Retention指明注解的信息在运行时也能获取到,而其中最关键的就是OnClassCondition条件类,里面是具体的条件计算逻辑:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
/**
* The classes that must be present. Since this annotation is parsed by loading class
* bytecode, it is safe to specify classes here that may ultimately not be on the
* classpath, only if this annotation is directly on the affected component and
* <b>not</b> if this annotation is used as a composed, meta-annotation. In order to
* use this annotation as a meta-annotation, only use the {@link #name} attribute.
* @return the classes that must be present
*/
Class<?>[] value() default {};
/**
* The classes names that must be present.
* @return the class names that must be present.
*/
String[] name() default {};
}
了解了条件注解后,再来看看它们是如何与配置类结合使用的。以JdbcTemplateAutoConfiguration为例:
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(JdbcProperties.class)
@Import({ DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class,
NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration {
}
可以看到这个配置类的生效条件是存在DataSource和JdbcTemplate类,且在上下文中只能有一个DataSource。此外,这个自动配置需要在DataSourceAutoConfiguration之后再配置(可以用@AutoConfigureBefore、@AutoConfigureAfter和@AutoConfigureOrder来控制自动配置的顺序)
2编写自已的自动配置
根据上面的描述,我们很容易想到,要编写自己的自动配置,只需要以下三个步骤:
(1)编写常规的配置类
(2)为配置类增加生效条件与顺序
(3)在/META-INF/spring.factories文件中添加自动配置类
2.1创建项目
在Spring Initializr中,创建一个Maven工程,添加如下依赖:
<dependencies>
<!-- 添加自动配置所使用的包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 用户在写配置文件时,会有提示效果 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.2编写一个简单的MyAutoConfigure类和配置类Bean
编写一个简单的MyAutoConfigure类,上面增加了@Configuration注解,表示这是一个配置类,这个配置类的生效条件是myconfig.ready属性的值为true,除此之外的值或者不存在该属性时MyAutoConfigure都不会生效。
/**
* TODO 1、编写配置类并指定文件
*
* @author ss_419
* @version 1.0
* @date 2023/3/17 21:24
*/
@Configuration
@EnableConfigurationProperties(CommonBean.class)
@ConditionalOnProperty(name = "myconfig.ready",havingValue = "true")
public class MyAutoConfigure {
}
/**
* TODO 2、创建配置类Bean
*
* @author ss_419
* @version 1.0
* @date 2023/3/17 22:40
*/
@ConfigurationProperties("myconfigbean")
@Data
public class MyConfigBean {
private boolean ready;
private String info;
}
2.3配置spring.factories文件
为了让SpringBoot能找到我们写的这个配置类,我们需要在src/resources目录中创建META-INF/spring.factories文件,其内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.pp.myspringbootstart.beans.MyAutoConfigure
2.4测试自动配置是否生效
@SpringBootTest
public class MyConfigurationEnableTest {
@Autowired
private ApplicationContext applicationContext;
@Test
void testPropertiesBeanAvailableTest() throws Exception {
assertNotNull(applicationContext.getBean(MyConfigBean.class));
assertTrue(applicationContext.containsBean("org.pp.myspringbootstart.beans.MyConfigBean"));
}
@Test
void testPropertyValues(){
MyConfigBean bean = applicationContext.getBean(MyConfigBean.class);
assertTrue(bean.isReady());
assertEquals("hello", bean.getInfo());
}
}
SpringBoot——自定义自动配置与起步依赖的更多相关文章
- SpringBoot入门(二)——起步依赖
本文来自网易云社区 在前一篇我们通过简单几步操作就生成了一个可以直接运行的Web程序,这是因为SpringBoot代替我们做了许多工作,概括来讲可以分为起步依赖和自动配置.这一篇先来看看起步依赖. 项 ...
- 面试题: SpringBoot 的自动配置原理
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 3.Spring Boot 的自动配置原理 package com.mmall; import org. ...
- Spring boot运行原理-自定义自动配置类
在前面SpringBoot的文章中介绍了SpringBoot的基本配置,今天我们将给大家讲一讲SpringBoot的运行原理,然后根据原理我们自定义一个starter pom. 本章对于后续继续学习S ...
- 关于SpringBoot的自动配置和启动过程
一.简介 Spring Boot简化了Spring应用的开发,采用约定大于配置的思想,去繁从简,很方便就能构建一个独立的.产品级别的应用. 1.传统J2EE开发的缺点 开发笨重.配置繁多复杂.开发效率 ...
- Springboot MVC 自动配置
Springboot MVC 自动配置 官方文档阅读 https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#w ...
- SpringBoot的自动配置
1.根据条件来装配bean,SpringBoot的自动配置,根据条件进行自动配置. 首先创建一个接口,如下所示: package com.bie.encoding; /** * * @Descript ...
- springboot(六)自动配置原理和@Conditional
官方参考的配置属性:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#common-appl ...
- springboot mvc自动配置(一)自动配置DispatcherServlet和DispatcherServletRegistry
所有文章 https://www.cnblogs.com/lay2017/p/11775787.html 正文 springboot的自动配置基于SPI机制,实现自动配置的核心要点就是添加一个自动配置 ...
- springboot mvc自动配置(三)初始化mvc的组件
所有文章 https://www.cnblogs.com/lay2017/p/11775787.html 正文 在springboot mvc自动配置的时候,获得了DispatcherServlet和 ...
- spring-boot spring-MVC自动配置
Spring MVC auto-configuration Spring Boot 自动配置好了SpringMVC 以下是SpringBoot对SpringMVC的默认配置:==(WebMvcAuto ...
随机推荐
- jenkins +docker+python接口自动化之docker下安装jenkins(一)
1.下载jenkins启动docker服务之后,首先搜索可用的jenkins镜像 docker search jenkins 第一个是官方版本,但是已标明废弃了,让用第二个jenkisn/jenkin ...
- Activiti工作流引擎系列-第二篇
官网案例下载安装实例 { "info": { "_postman_id": "64f2d7ca-8287-4f8d-94ba-1138861877dd ...
- ZSTUOJ刷题④:Problem B.--输出双层金字塔
Problem B: 输出双层金字塔 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 7860 Solved: 5834 Description 输出双层 ...
- 关于JDK1.8 java HashMap的tableSizeFor的解析:一个数最近2的幂次数方法
简介 一个数的最近2的幂次数,是java hashmap初始化方法指定容量里面对容量进行处理采用的方法 1.位运算符号介绍 符号 描述 运算规则 & 与 两个位都为1时,结果才为1 | 或 两 ...
- bzoj 3532
很好的一道题,对理解最小割有很大帮助 首先,不难发现本题与网络流24题中的某一道很类似,我们可以先跑一次dp求出每个节点的LIS,然后拆点,拆出的两点之间连流量为删除的代价的边,剩下的点之间按dp的转 ...
- bzoj 3561
题意:求$\sum_{i=1}^{n}\sum_{j=1}^{n}lcm(i,j)^{gcd(i,j)}$ 神仙题... 首先可能会想到一个转化,就是$lcm(i,j)=\frac{ij}{gcd(i ...
- source Insight 的常用设置
1. 去除^M 的显示 "Options->Preferences->Files", 设置"Default File Format" to &quo ...
- Liunx安装Docker
1.更新yum包到最新 sudo yum update 2.卸载历史Docker,如果没有安装过,则跳过该步 sudo yum remove docker \ docker-client \ dock ...
- win 端口占用
netstat -aon|findstr "8080" 查看端口 TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 11468 TCP 172.27.232 ...
- 4组-Beta冲刺-5/5
一.基本情况 队名:摸鲨鱼小队 组长博客:https://www.cnblogs.com/smallgrape/p/15608986.html github链接:https://github.com/ ...