自定义Starter
- 在SpringBoot中我们已经分析了stater的原理,现在我们自己手写一个starter
自定义starter的步骤
(1)自定义starter
(2)使用starter
代码实现创建starter
- 引入maven依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>tuling</artifactId>
<groupId>com.xiyou</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>starter</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.0.0.RELEASE</version>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>
</dependencies>
<build>
<finalName>person-spring-boot-starter</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 这里我们导入了spring-boot-configuration-processor,是因为我们使用了SpringBoot的自动装配功能,所以需要导入该依赖
- 定义XXXProperties类
package com.xiyou.po;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author 92823
*/
@Component
@ConfigurationProperties(prefix = "spring.person")
@Data
public class PersonProperties {
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private String sex;
}
- 定义该类的原因就是为了让我们在使用该starter的时候yml中的配置文件可以注入进去
- 上面标示的是只要我们在yml文件中以spring.person开始的配置都会自动注入进去
- 核心服务类(Service)
package com.xiyou.service;
import com.xiyou.po.PersonProperties;
import org.springframework.stereotype.Service;
/**
* @author 92823
*/
public class PersonService {
private PersonProperties personProperties;
public PersonService() {
}
public PersonService (PersonProperties personProperties) {
this.personProperties = personProperties;
}
public void sayHello() {
System.out.println(personProperties);
}
}
- 注意这个Service没有写@Service,因为我们会通过在配置类中利用@Bean将其注入,顺便还会用上@Conditional
- 这里的属性PersonProperties也不是通过@Autowrited注入的(可以通过这么注入,但是这里是通过构造函数进去的)
- 自动配置类
package com.xiyou.config;
import com.xiyou.po.PersonProperties;
import com.xiyou.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 92823
*/
@EnableConfigurationProperties(PersonProperties.class)
@Configuration
@ConditionalOnClass({PersonService.class})
public class PersonAutoConfiguration {
@Autowired
private PersonProperties personProperties;
/**
* 声明bean对象
* 当我们容器中没有PersonService的时候 就自动创建这个Bean
*/
@Bean
@ConditionalOnMissingBean(PersonService.class)
public PersonService personService () {
PersonService personService = new PersonService(personProperties);
return personService;
}
}
- 仔细看这个类,我们在类上面加了注解:
(1)@EnableConfigurationProperties(PersonProperties.class):开启自动装配,将yml的配置文件装配到PersonProperties中
(2)@Configuration:开启配置
(3)@ConditionalOnClass({PersonService.class}):当类路径classpath下有PersonService类的情况下进行自动配置有PersonService类的时候加载 - 我们在方法上面加入了
(1) @Bean
(2)@ConditionalOnMissingBean(PersonService.class):当Spring容器中没有PersonService的bean的时候,加载该Bean到容器中 - 注意:
@ConditionalOnClass:当类路径classpath下有指定的类的情况下进行自动配置
@ConditionalOnMissingBean:当容器(Spring Context)中没有指定Bean的情况下进行自动配置
- 写自己的spring.factories
- 在resources目录中新建META-INF目录,在下面新建spring.factories文件,里面写org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xiyou.config.PersonAutoConfiguration
- 打包该maven
- mvn clean install
代码实现使用该starter
- 上面我们已经创建了starter,现在我们开始使用
- 创建maven依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>tuling</artifactId>
<groupId>com.xiyou</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>web</artifactId>
<dependencies>
<dependency>
<groupId>com.xiyou</groupId>
<artifactId>starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
- 这里我们导入了自己的starter
- 配置yml文件
server:
port: 8889
spring:
person:
name: zyf
age: 25
sex: F
- 可以看到我们在这里配置了相关的属性,这里以spring.person开头
- 写一个controller类进行测试
package com.xiyou.controller;
import com.xiyou.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 92823
*/
@RestController
public class TestController {
@Autowired
PersonService personService;
@GetMapping("/get")
public String test() {
personService.sayHello();
return "ok";
}
}
- 这时候当我们访问get的时候,我们看是否可以正常调用sayHello方法
- 结果
- 这里我们发现其可以正常调用,证明我们已经将PersonService 注入进去,但是我们没有配置PersonService类,这里就可以证明我们配置的starter已经正常自动加载了配置。