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()); } }
posted on 2023-03-17 23:18 JavaCoderPan 阅读(495) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南