`

转: SpringBoot编写自定义的starter

 
阅读更多

转:SpringBoot编写自定义的starter

 原文:http://www.importnew.com/24164.html

 

 

在之前的文章中,我们分析过SpringBoot内部的自动化配置原理自动化配置注解开关原理

我们先简单分析一下mybatis starter的编写,然后再编写自定义的starter。

mybatis中的autoconfigure模块中使用了一个叫做MybatisAutoConfiguration的自动化配置类。

这个MybatisAutoConfiguration需要在这些Condition条件下才会执行:

  1. @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })。需要SqlSessionFactory和SqlSessionFactoryBean在classpath中都存在
  2. @ConditionalOnBean(DataSource.class)。 spring factory中需要存在一个DataSource的bean
  3. @AutoConfigureAfter(DataSourceAutoConfiguration.class)。需要在DataSourceAutoConfiguration自动化配置之后进行配置,因为mybatis需要数据源的支持

同时在META-INF目录下有个spring.factories这个properties文件,而且它的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration,这样才会被springboot加载:

1
2
3
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

有了这些东西之后,mybatis相关的配置会被自动加入到spring container中,只要在maven中加入starter即可:

1
2
3
4
5
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>

编写自定义的starter

接下来,我们来编写自定义的starter:log-starter。

这个starter内部定义了一个注解,使用这个注解修饰方法之后,该方法的调用会在日志中被打印并且还会打印出方法的耗时。starter支持exclude配置,在exclude中出现的方法不会进行计算。

pom文件:

1
2
3
4
5
6
7
8
9
10
11
12
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starters</artifactId>
    <version>1.3.5.RELEASE</version>
</parent>
 
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

定义修饰方法的注解@Log:

1
2
3
4
5
6
7
8
9
10
package me.format.springboot.log.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;   
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log { }

然后是配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package me.format.springboot.log.autoconfigure;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.StringUtils;
 
import javax.annotation.PostConstruct;
 
@ConfigurationProperties(prefix = "mylog")
public class LogProperties {
 
    private String exclude;
 
    private String[] excludeArr;
 
    @PostConstruct
    public void init() {
        this.excludeArr = StringUtils.split(exclude, ",");
    }
 
    public String getExclude() {
        return exclude;
    }
 
    public void setExclude(String exclude) {
        this.exclude = exclude;
    }
 
    public String[] getExcludeArr() {
        return excludeArr;
    }
}

接下来是AutoConfiguration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package me.format.springboot.log.autoconfigure;
 
import me.format.springboot.log.annotation.Log;
import me.format.springboot.log.aop.LogMethodInterceptor;
import org.aopalliance.aop.Advice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
 
import javax.annotation.PostConstruct;
 
@Configuration
@EnableConfigurationProperties(LogProperties.class)
public class LogAutoConfiguration extends AbstractPointcutAdvisor {
 
    private Logger logger = LoggerFactory.getLogger(LogAutoConfiguration.class);
 
    private Pointcut pointcut;
 
    private Advice advice;
 
    @Autowired
    private LogProperties logProperties;
 
    @PostConstruct
    public void init() {
        logger.info("init LogAutoConfiguration start");
        this.pointcut = new AnnotationMatchingPointcut(null, Log.class);
        this.advice = new LogMethodInterceptor(logProperties.getExcludeArr());
        logger.info("init LogAutoConfiguration end");
    }
 
    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }
 
    @Override
    public Advice getAdvice() {
        return this.advice;
    }
 
}

由于计算方法调用的时候需要使用aop相关的lib,所以我们的AutoConfiguration继承了AbstractPointcutAdvisor。这样就有了Pointcut和Advice。Pointcut是一个支持注解的修饰方法的Pointcut,Advice则自己实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package me.format.springboot.log.aop;
 
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.util.Arrays;
import java.util.List;
 
public class LogMethodInterceptor implements MethodInterceptor {
    private Logger logger = LoggerFactory.getLogger(LogMethodInterceptor.class);
    private List<String> exclude;
    public LogMethodInterceptor(String[] exclude) {
        this.exclude = Arrays.asList(exclude);
    }
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        String methodName = invocation.getMethod().getName();
        if(exclude.contains(methodName)) {
            return invocation.proceed();
        }
        long start = System.currentTimeMillis();
        Object result = invocation.proceed();
        long end = System.currentTimeMillis();
        logger.info("====method({}), cost({}) ", methodName, (end - start));
        return result;
    }
}

最后resources/META-INF/spring.factories中加入这个AutoConfiguration:

1
2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
me.format.springboot.log.autoconfigure.LogAutoConfiguration

我们在项目中使用这个log-starter:

1
2
3
4
5
<dependency>
    <groupId>me.format.springboot</groupId>
    <artifactId>log-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

使用配置:

1
mylog.exclude=core,log

然后编写一个简单的Service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
public class SimpleService {
 
    @Log
    public void test(int num) {
        System.out.println("----test---- " + num);
    }
 
    @Log
    public void core(int num) {
        System.out.println("----core---- " + num);
    }
 
    public void work(int num) {
        System.out.println("----work---- " + num);
    }
 
}

使用单元测试分别调用这3个方法,由于work方法没有加上@Log注解,core方法虽然加上了@Log注解,但是在配置中被exclude了,只有test方法可以正常计算耗时:

1
2
3
4
----test---- 666
2016-11-16 01:29:32.255  INFO 41010 --- [           main] m.f.s.log.aop.LogMethodInterceptor       : ====method(test),     cost(36)
----work---- 666
----core---- 666

总结:

自定义springboot的starter,注意这两点。

  1. 如果自动化配置类需要在程序启动的时候就加载,可以在META-INF/spring.factories文件中定义。如果本次加载还需要其他一些lib的话,可以使用ConditionalOnClass注解协助
  2. 如果自动化配置类要在使用自定义注解后才加载,可以使用自定义注解+@Import注解或@ImportSelector注解完成

参考:

http://www.jianshu.com/p/85460c1d835a

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html

分享到:
评论

相关推荐

    SpringBoot自定义starter实例代码

    我们可以参照 spring-boot-starter,我们发现其中没有代码,我们在看它的 pom 中的依赖中有个 springboot-starter: ```xml &lt;groupId&gt;org.springframework.boot &lt;artifactId&gt;spring-boot-starter ``` 我们再看看...

    SpringBoot自定义starter入门

    最后,自定义Starter的目的是为了提高代码的复用性和可维护性。当你有一个通用的功能或一组组件,希望在多个Spring Boot项目中使用时,创建一个Starter是一个明智的选择。通过遵循Spring Boot的设计原则和最佳实践,...

    使用了自定义springboot-starter组件的示例项目【study-springboot】

    总结,本项目【study-springboot】是一个实践案例,展示了如何在Spring Boot项目中使用自定义Starter组件。这不仅简化了配置,提高了代码的可复用性,同时也使得项目的构建和维护变得更加高效。通过分析项目文件和...

    springboot自定义starter

    现在,让我们按照以下步骤创建一个自定义Starter: 1. **初始化项目**:使用Spring Initializr或者通过Maven Archetype创建一个新的Spring Boot项目,选择适当的依赖(如Web、Data JPA等)。 2. **创建pom.xml**:...

    SpringBoot启动配置原理_SpringBoot自定义starters.zip

    这个压缩包文件 "SpringBoot启动配置原理_SpringBoot自定义starters.zip" 显然是关于理解 Spring Boot 启动配置以及如何自定义 Starters 的教程资料。 **Spring Boot 启动配置原理** Spring Boot 的核心之一是其...

    SpringBoot第 14 讲:SpringBoot+MyBatisPlus(代码)

    MyBatisPlus会自动为实体类生成Mapper接口,但为了更灵活地编写SQL,我们通常还会自定义Mapper接口。例如,有一个`User`实体类,我们可以创建对应的`UserMapper`接口和`UserMapper.xml`文件。 在实体类中,我们需要...

    springboot自定义Starter的具体流程

    SpringBoot自定义Starter的具体流程 SpringBoot自定义Starter是一种特殊的starter,它可以根据项目的需求进行自定义和配置,从而满足不同的业务需求。在 본节中,我们将详细介绍SpringBoot自定义Starter的具体流程...

    my-springboot-starter.zip

    通过创建自定义Starter,我们可以将常见的配置、依赖和初始化逻辑打包,使得在新项目中使用这些功能时,只需添加一个Maven或Gradle依赖即可。 在创建自定义Starter时,通常包括以下几个关键步骤: 1. **定义Maven...

    如何自定义一个SpringBoot中的starter代码实例.zip

    为了验证自定义starter是否正常工作,需要编写测试用例。使用`@SpringBootTest`和`@Import`注解来加载自定义的starter,然后通过断言来确认预期的bean是否被正确地创建和配置。 8. **发布到Maven仓库** 将`my-...

    xfan_springBoot:SpringBoot学习扩展

    3. **起步依赖(Starter POMs)**:SpringBoot通过一系列的起步依赖简化了Maven或Gradle的构建配置,如`spring-boot-starter-web`用于web应用,`spring-boot-starter-data-jpa`用于数据库访问。 4. **内嵌式容器**...

    driver_springboot.zip

    - **起步依赖**(Starter POMs):SpringBoot的Maven或Gradle模块提供了预配置的依赖集合,如`spring-boot-starter-web`用于Web开发。 - **内嵌服务器**:SpringBoot内建了Tomcat或Jetty等HTTP服务器,无需额外...

    基于springboot的jenkins的pipeline项目.zip

    1. **起步依赖**:通过`spring-boot-starter`模块,可以轻松引入如Web、Data JPA、Actuator等关键功能。 2. **内嵌Web服务器**:如Tomcat或Jetty,无需额外配置即可启动HTTP服务。 3. **自动配置**:SpringBoot尝试...

    关于书后台SpringBoot做的

    2. **起步依赖**(Starters):SpringBoot的起步依赖是一种方便的Maven或Gradle配置,比如`spring-boot-starter-data-jpa`用于JPA数据访问,`spring-boot-starter-web`用于Web开发,它们帮助开发者快速添加所需依赖...

    SpringBoot入门基础以及应用

    3. **提高开发效率**:由于SpringBoot内置了各种starter依赖,开发人员只需要引入所需的starter即可获得完整的功能,极大地提高了开发效率。 4. **简化部署**:SpringBoot支持打包成独立的JAR或WAR文件,这些文件...

    Springboot开发:Springboot shiro权限管理,流程最详细、代码最干净、配置最简单的shiro上手项目

    此外,还需要编写一个Shiro配置类,继承自`WebSecurityConfigurerAdapter`,重写其方法来配置Shiro的FilterChainDefinitionSource,以及自定义的Realm。 认证流程主要包括以下步骤: 1. 用户提交用户名和密码。 2. ...

    springboot自定义自动装配.rar

    要创建自定义Starter,需编写`pom.xml`文件引入相关依赖,并创建自动配置类。 2. **命名规范**:自定义Starter的Maven模块名通常以`spring-boot-starter-`开头,如`spring-boot-starter-myapp`。 3. **`spring....

    基于 SpringBoot实现的开发者社区.zip

    5. **运行时 Banner**:SpringBoot允许自定义启动时的Banner,展示项目信息。 6. **命令行界面(CLI)**:SpringBoot还提供了命令行工具,方便快速执行脚本和测试。 7. **YAML/Properties配置**:SpringBoot支持...

    Spring boot创建自定义starter的完整步骤

    Spring Boot的自定义starter是开发人员扩展其功能和定制化应用的一种强大方式。本文将详细介绍创建自定义starter的完整步骤,以及如何利用starter模块来优化项目配置。 首先,理解starter的作用至关重要。starter是...

    springboot demo整合

    在SpringBoot中,`META-INF/spring.factories`文件可以用来声明自定义的配置初始化类。 9. **数据库集成**:SpringBoot与多种数据库兼容,如MySQL、Oracle等。使用`spring-boot-starter-data-jpa`可以快速集成JPA...

    SpringBoot入门.pptx

    - **起步依赖(Starters)**:SpringBoot通过起步依赖来引入特定功能的库,例如Spring Web Starter,它包含Spring MVC和相关依赖,极大地简化了pom.xml文件。 - **自动化配置**:SpringBoot通过@...

Global site tag (gtag.js) - Google Analytics