实现自己的springboot starter

为什么可以自定义starter?

当然是spring官方提供了相应的接口,让第三方自己去集成springboot,因为spring官方的人员不可能提供所有的starter,但是不知道为什么Druid不是spring官方集成的?

我为什么去探究springboot starter呢?

我考虑的是springboot提到的是默认包扫描路径是启动类的子包,那么加入的这些starter显然不是在这个路径下,为什么可以被spring管理呢,这些starter做了什么操作。在研究完了springboot starter后,就有了这个自定义的car-spring-boot-starter。

实现自己的car-spring-boot-starter

项目概要描述

这里会涉及到两个maven工程,springboot-starter-car和springboot-starter-test-car,第一个是我们要构建的starter,第二个是springboot工程用于测试我们的starter是否能正常使用。

工程目录截图

springboot-starter-car工程目录                      springboot的测试工程目录

构建springboot-starter-car工程

1.创建maven工程,引入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">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.lzy.springboot.starter.car</groupId>
	<artifactId>car-springboot-starter</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-autoconfigure</artifactId>
			<version>1.5.2.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<version>1.5.2.RELEASE</version>
			<optional>true</optional>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>  

2.创建CarProperties类,该类就是一个接受配置的pojo,使用@ConfigurationProperties(prefix = "car")指定了接受配置文件参数的前缀

package com.lzy.springboot.starter.car;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 接受配置文件的pojo
 * 
 * @author admin
 *
 */
// 定义application.properties配置文件中的配置前缀
@ConfigurationProperties(prefix = "car")
public class CarProperties {

	// 价格
	private int price;
	// 重量
	private int weight;

	get/set方法省略
}

3.创建CarService类,该类是这个starter对外所提供的服务,这里仅提供获取价格和重量的服务

package com.lzy.springboot.starter.car.service;  
  
import com.lzy.springboot.starter.car.CarProperties;  
/**
 * 引入该starter后,通过配置文件的信息可以提供什么功能
 * 
 * @author admin
 *
 */
public class CarService {  
      
    private CarProperties properties;  
      
    public CarService(CarProperties properties){  
        this.properties = properties;  
    }  
      
    public CarService(){  
          
    }  
      
    public int getCarPrice(){  
        return properties.getPrice();  
    }  
      
    public int getCarWeight(){  
        return properties.getWeight();  
    }  
      
    
}  

4.创建自动配置类CarAutoConfiguration,主要是将配置文件的信息读取到CarProperties中,并将CarService服务实例化。代码中已经给了详细解释,就不再赘述。

package com.lzy.springboot.starter.car.conf;


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.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.lzy.springboot.starter.car.CarProperties;
import com.lzy.springboot.starter.car.service.CarService;
// 配置注解  ,标记该类是个配文类
@Configuration 
// 开启指定类的配置,既是接受配置文件中的参数的类, 多个时我们可以这么写value={Properties1.class,Properteis2.class....}
@EnableConfigurationProperties(CarProperties.class) 
// 当这个类(CarService)在classPath下,并且容器 中没有相同的,就自动配置 
@ConditionalOnClass(CarService.class)
// 表示只有我们的配置文件是否配置了以car为前缀的资源项值,并且在该资源项值为enabled,如果没有配置我们默认设置为enabled
@ConditionalOnProperty(prefix="car", value="enabled", matchIfMissing=true)
public class CarAutoConfiguration {  
    @Autowired  
    private CarProperties properties;  
      
    @Bean  
    @ConditionalOnMissingBean(CarService.class)// 当容器中没有指定Bean的情况下,自动配置carService类  
    public CarService carService(){  
        CarService personService = new CarService(properties);  
        return personService;  
    }  
}  

这里再提一点就是这个类可能用到的注解

@ConditionalOnBean:当容器中有指定的Bean的条件下  
@ConditionalOnClass:当类路径下有指定的类的条件下  
@ConditionalOnExpression:基于SpEL表达式作为判断条件  
@ConditionalOnJava:基于JVM版本作为判断条件  
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置  
@ConditionalOnMissingBean:当容器中没有指定Bean的情况下  
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下  
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下  
@ConditionalOnProperty:指定的属性是否有指定的值  
@ConditionalOnResource:类路径下是否有指定的资源  
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean  
@ConditionalOnWebApplication:当前项目是Web项目的条件下  

摘抄地址:https://blog.csdn.net/liuchuanhong1/article/details/55057135

5.在src/main/resources新建META-INF文件夹,在META-INF文件夹下新建spring.factories文件,写入

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lzy.springboot.starter.car.conf.CarAutoConfiguration

spring.factories的内容是给springboot启动时读取的。当然也可以使用注解方式代替该文件,在启动类上添加@ImportAutoConfiguration({CarAutoConfiguration.class}) 。

6.使用maven命令打包,eclipse可以直接使用如下方式打包并安装到本地maven库

7.测试,新建一个springboot项目springboot-starter-test-car,引入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 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
    <modelVersion>4.0.0</modelVersion>  
  
    <groupId>com.lzy.springboot.starter.car.test</groupId>  
    <artifactId>springboot-starter-car</artifactId>  
    <version>0.0.1-SNAPSHOT</version>  
    <packaging>jar</packaging>  
    <parent>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-parent</artifactId>  
        <version>1.5.1.RELEASE</version>  
        <relativePath /> <!-- lookup parent from repository -->  
    </parent>  
  
    <properties>  
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
        <java.version>1.8</java.version>  
    </properties>  
  
    <dependencies>  
        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter</artifactId>  
        </dependency>  
          
        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-web</artifactId>  
        </dependency>  
  
        <dependency>
        <!-- 引入car-springboot-starter -->  
            <groupId>com.lzy.springboot.starter.car</groupId>  
            <artifactId>car-springboot-starter</artifactId>  
            <version>0.0.1-SNAPSHOT</version>  
        </dependency>  
  
        <dependency>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-test</artifactId>  
            <scope>test</scope>  
        </dependency>  
    </dependencies>  
  
    <build>  
        <plugins>  
            <plugin>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-maven-plugin</artifactId>  
            </plugin>  
        </plugins>  
    </build>  
</project>  

8.创建测试接口 PersonServiceController

package com.lzy.springboot.starter.car.controller;  
  
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.lzy.springboot.starter.car.service.CarService;  
  
@RestController  
public class PersonServiceController {  
	// 自动注入starter中的carService  
    @Autowired 
    private CarService carService;  
      
    @GetMapping("/get/price")  
    public int getCarPrice(){ 
    	// 调用PersonService服务的方法
        return carService.getCarPrice();
    }  
      
    @GetMapping("/get/weight")  
    public int getCarWeight(){  
        return carService.getCarWeight(); 
    }  
}  

9.启动项目,访问http://localhost:8080/get/price ,能得到配置文件中的值,就说明starter创建成功。

猜你喜欢

转载自my.oschina.net/u/2528990/blog/1806182