Springboot之starter
大约 2 分钟SpringJavaSpring Boot
0x1 starter介绍
starter是可插拔插件,springBoot自带了很多的starter,它与jar包的区别是starter能自动实现配置,极大提升了开发人员的效率。
0x2 conditional相关注解介绍
starter大量使用了conditional注解,conditional的作用是根据是否满足特定条件来决定是否创建某个特定的Bean,这是Springboot实现自动配置的关键基础能力。常见的conditional注解有:
- @ConditioncalOnBean
- @ConditionalOnMissBean
- @ConditionalOnClass
- @ConditionalOnMissingClass
- @ConditionalOnWebApplication
- @ConditionalOnProperty (判断特定属性是否存在)
- @ConditionalOnNotWebApplication (判断是否为Web环境)
- @ConditionalOnJava (判断java版本)
对于上述注解的使用在这里不过多阐述,下面实现自己的conditional注解。
首先定义注解类:
package com.example.demo.conditional;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
/**
* @Author : yangliu@tiduyun.com
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({PropertiesConditional.class})
public @interface MyConditionalOnProperties {
String[] value() default {};
}
实现:
package com.example.demo.conditional;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
/**
* @Author : yangliu@tiduyun.com
*/
public class PropertiesConditional implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 获取数据
final String[] properties = (String[])metadata
.getAnnotationAttributes("com.example.demo.conditional.MyConditionalOnProperties").get("value");
for (String property : properties) {
if (StringUtils.isEmpty(context.getEnvironment().getProperty(property))) {
return false;
}
}
return true;
}
}
测试,声明类A,使用自定义注解,此时没有xw.name属性,类A没有进行注入,使用类A会引起报错,添加变量后成功。
package com.example.demo.conditional;
import org.springframework.stereotype.Component;
/**
* @Author : yangliu@tiduyun.com
*/
@Component
@MyConditionalOnProperties({"xw.name"})
public class A {
}
package com.example.demo;
import com.example.demo.conditional.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication
@PropertySource(value ={"classpath:a/a.properties", "classpath:b.properties"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Autowired
private A a;
}
0x3 自定义starter
新建Mylog
package com.example.starter.log;
/**
* @Author : yangliu@tiduyun.com
*/
public interface MyLog {
void log(String value);
}
DefaultLog类
package com.example.starter.log;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Component;
/**
* @Author : yangliu@tiduyun.com
*/
@ConditionalOnMissingBean(value = ErrorMyLog.class)
public class DefaultMyLog implements MyLog {
@Override
public void log(String value) {
System.out.println("default log method " + value);
}
}
在src/main/resources/META-INF/spring.factories
启动自动加载
org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx
ErrorLog类:
package com.example.starter.log;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
/**
* @Author : yangliu@tiduyun.com
*/
@Component
@ConditionalOnProperty(value = "error.log", havingValue = "true")
public class ErrorMyLog implements MyLog {
@Override
public void log(String value) {
System.out.println("error log " + value);
}
}
主要代码如上,当有error.log属性并且值为true时使用ErrorLog,否则使用DefaultLog。pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>log-sping-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>starter</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.0-M5</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
</dependencyManagement>
<!-- <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>-->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>