IT技术篇springbootfeign

Spring boot构建自定义的starter

2017-11-04  本文已影响146人  maskwang520

  在我们日常用springboot的开发过程中,经常会遇到使用如下的一个类来代表程序的入口类。即

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

包括我自己,我平常在开发的过程中,并没有去重点关注spring boot的运行原理,大家都是约定俗成的这么去使用。接下的过程中,将会结合源码简单的分析下springboot运行原理。

一.Springboot 自动配置原理分析

@SpringBootApplication注解@SpringBootApplication是一个复合注解,它包括@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan三个注解。其中最关键的莫过@EnableAutoConfiguration这个注解。在它的源码中加入了这样一个注解@Import({EnableAutoConfigurationImportSelector.class})EnableAutoConfigurationImportSelector,它使用SpringFactoriesLoader. loadFactoryNames方法来扫描META-INF/spring.factories文件,此文件中声明了有哪些自动配置。源码如下(我挑选出重要的一部分)

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        try {
            Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            List<String> result = new ArrayList<String>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
                    "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }

我随便查看spring-boot-autoconfigure-1.5.3.RELEASE.jar中的spring.factories,有如下的自动配置。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\

上述spring.factories对应key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值即为启动时候需要自动配置的类。

二. 实现自定义的starter

  1. 首先定义一个基本的对象类,用来接收application.properties里面特定字段的值。
@ConfigurationProperties(prefix = "hello")
public class HelloServiceProperties {
    private static final String MSG="world";
    private String msg=MSG;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}
  1. 先定义条件类(根据此类的存在与否来创建这个类的Bean,这个类可以是第三方类库的类)。
public class HelloService {
    private String msg;
    public String sayHello(){
        return msg;
    }
    public void setMsg(String msg){
        this.msg=msg;
    }
}
  1. 自动配置类
@Configuration  //1
@EnableConfigurationProperties(HelloServiceProperties.class)//2
@ConditionalOnClass(HelloService.class)   //3
@ConditionalOnProperty(prefix = "hello",value = "enabled",matchIfMissing = true)  //4
public class HelloServiceAutoConfiguration {

    @Autowired
    private HelloServiceProperties helloServiceProperties;

    @Bean
    @ConditionalOnMissingBean(HelloService.class)  //5
    public HelloService helloService(){
        HelloService helloService=new HelloService();
        helloService.setMsg(helloServiceProperties.getMsg());
        return helloService;
    }
}

配置好之后,我们还需要在src\main\resources下新建文件夹WEB-INF,再新建文件spring.factories里面的内容如下

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.springboot.mystartertool.HelloServiceAutoConfiguration

里面指定的类是上面自定义的那个配置类HelloServiceAutoConfiguration

定义spring.factories的原因是因为@EnableAutoConfiguration会扫描jar包下所有spring.factories文件,从而构造自动配置类。我们使用的时候使用@Autowired注入就行。

在以上工作完成后,我们执行如下命令

    mvn clean install

就将项目打包到本地maven仓库中,有条件的可以安装的到私服中。

三. 应用自定义starter

  1. 首先引入自定义的starter的jar包
 <!--引入我的start-->
        <dependency>
            <groupId>com.maskwang</groupId>
            <artifactId>Springboot-mystart</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
  1. 当我们在application.properties配置如下
hello.msg=maskwang

我们就可以使用自定义的starter啦。

@RestController
public class HelloController {
    @Autowired
    HelloService helloService;
    @RequestMapping("/hello")
    public String hello() {
        return helloService.sayHello();
    }
}

由于我们没有自定义HelloService,所以会配置类会发挥作用,新建一个HelloService,并把里面的msg设置成”maskwang"。没有配置msg,则会采用默认的。结果如下

image.png

参考文献:

  1. 使用 Java 配置进行 Spring bean 管理
  2. Spring boot实战(汪云飞著)
    github地址
上一篇 下一篇

猜你喜欢

热点阅读