springboot-自定义starter

it2025-08-02  6

在实际业务开发过程当中,有很多公共的功能。针对这些功能,可以自己开发公共的starter模块

命名

对于自己开发的starter模块,一般使用xxx-spring-boot-starter,而spring自己生态圈的starter,一般都是spring-boot-starter-xxx格式命名

maven依赖(pom.xml)

<!-- 版本自己定 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> </dependencies>

属性类

package com.leewan.vue.starter.properties; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "leewan.vue") public class LeewanVueProperties { private String rootPath; public String getRootPath() { return rootPath; } public void setRootPath(String rootPath) { this.rootPath = rootPath; } }

通过@ConfigurationProperties注解,注入属性

配置类(最核心)

package com.leewan.vue.starter.config; import com.leewan.vue.starter.condition.ConditionalHasProperties; import com.leewan.vue.starter.controller.LeewanPageController; import com.leewan.vue.starter.pageContext.ClassPathPageContext; import com.leewan.vue.starter.pageContext.FilePageContext; import com.leewan.vue.starter.pageContext.PageContext; import com.leewan.vue.starter.properties.LeewanVueProperties; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.ResourceUtils; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.lang.reflect.Method; import java.net.URL; @Configuration //开启LeewanVueProperties配置对象,如不配置,则无法自动注入LeewanVueProperties类 @EnableConfigurationProperties(LeewanVueProperties.class) //条件注解 @ConditionalHasProperties(propertyName = "leewan.vue.root-path") public class LeewanVueConfiguration { @Autowired private LeewanVueProperties properties; @Bean public PageContext pageContext() { String rootPath = properties.getRootPath(); if(rootPath.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) { String path = rootPath.substring(ResourceUtils.CLASSPATH_URL_PREFIX.length()); URL url = Thread.currentThread().getContextClassLoader().getResource(path); if(ResourceUtils.isJarURL(url)) { return new ClassPathPageContext(path); }else { return new FilePageContext(rootPath); } }else { return new FilePageContext(rootPath); } } @Bean("leewanPageController") public LeewanPageController pageController(){ return new LeewanPageController(); } @Bean public ApplicationContextAware aware(){ return new ApplicationContextAware() { @Override public void setApplicationContext(ApplicationContext application) throws BeansException { //手动注册controller RequestMappingHandlerMapping handlerMapping = application.getBean(RequestMappingHandlerMapping.class); try { Method method=handlerMapping.getClass().getSuperclass().getSuperclass(). getDeclaredMethod("detectHandlerMethods",Object.class); method.setAccessible(true); method.invoke(handlerMapping, "leewanPageController"); } catch (Exception e) { e.printStackTrace(); } } }; } } @EnableConfigurationProperties(LeewanVueProperties.class)

表示开启LeewanVueProperties配置对象,否则无法注入LeewanVueProperties对象

后续使用IDE(如idea,eclipse)编辑yml文件时,会根据LeewanVueProperties进行自动提示

条件注解

有些starter虽然引入,但实际运行过程中 需要满足一些特定条件才会运行。所以还需要条件注解来进行判断。springboot自带了很多条件注解,如@ConditionalOnProperty、@ConditionalOnBean等。

但是对于一些比较复杂的业务场景,使用spring自带的条件注解无法满足需求时,我们还可以自定义注解。 自定义注解一般需要两个类,一是注解,一是具体的条件匹配实现类

注解类
package com.leewan.vue.starter.condition; import org.springframework.context.annotation.Conditional; //配置条件匹配类 @Conditional(HasPropertiesCondition.class) public @interface ConditionalHasProperties { String propertyName() default ""; }
条件匹配实现类

需要实现org.springframework.context.annotation.Condition类, 通过AnnotatedTypeMetadata可以获取注解类里的一些配置 通过conditionContext可以获取上下文一些配置参数

package com.leewan.vue.starter.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.util.StringUtils; import java.util.Map; public class HasPropertiesCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { Map<String, Object> annotationAttributes = annotatedTypeMetadata.getAnnotationAttributes(ConditionalHasProperties.class.getName()); String propertyName = (String) annotationAttributes.get("propertyName"); String property = conditionContext.getEnvironment().getProperty(propertyName); if(StringUtils.hasText(property)){ return true; } return false; } }

配置文件

最后需要告诉spring 你的这个starter的自动配置类是哪个。通过配置文件进行配置 1、resources目录下 新建META-INF目录 2、新建文件spring.factories 3、在spring.factories中

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.leewan.vue.starter.config.LeewanVueConfiguration

一切搞定

最新回复(0)