自定义Spring-Boot @Enable注解

Spring-Boot中有很多Enable开头的注解,通过添加注解来开启一项功能,如

其原理是什么?如何开发自己的Enable注解?

1.原理

以@EnableScheduling为例,查看其源码,发现添加了一个@Import注解

继续查看@Import注解源码,发现其是由Spring提供的,用来导入配置类的,在配置类中定义的Bean(@Bean),可通过@Autowired注入到容器中,也就是可以被扫描到

 

2.自定义

了解了Enable注解的原理,我们就可以开发自己的Enable注解了,下面的例子实现了通过@Enable注解方式开启服务器负载监控的功能

2.1 定义定时任务类

package com.yc.dudu.common.monitor;

import com.alibaba.fastjson.JSONObject;
import com.sun.management.OperatingSystemMXBean;
import com.yc.dudu.common.constant.CommonConstants;
import com.yc.dudu.common.util.DateTimeUtil;
import com.yc.dudu.common.vo.ServerMonitorInfo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 收集服务器负载信息
 *
 * @author zhya
 * @date 2018/9/20
 **/
@Slf4j
@EnableScheduling
public class ServerLoadMonitorRunner implements CommandLineRunner {
    /**
     * 自定义log,输出服务器负载信息到日志文件
     */
    private static final Logger monitorLog = LoggerFactory.getLogger("serverMonitorLog");

    /**
     * 系统信息
     */
    private static final OperatingSystemMXBean mem = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    /**
     * 收集服务器负载信息并输出到日志文件
     */
    @Scheduled(cron = "*/5 * * * * ?")
    public void collectServerSystemLoad() {
        try {
            // 输出json格式的信息到文件
            monitorLog.info(JSONObject.toJSONString(new ServerMonitorInfo(InetAddress.getLocalHost().getHostName(),
                    String.valueOf(mem.getFreePhysicalMemorySize() / CommonConstants.BYTES_TO_MB),
                    String.valueOf(mem.getSystemCpuLoad()),
                    String.valueOf(File.listRoots()[0].getFreeSpace() / CommonConstants.BYTES_TO_MB),
                    DateTimeUtil.getNowDateTimeStr())));
        } catch (UnknownHostException e) {
            log.error(e.getMessage());
        }
    }

    /**
     * Callback used to run the bean.
     *
     * @param args incoming main method arguments
     * @throws Exception on error
     */
    @Override
    public void run(String... args) throws Exception {
        try {
            collectServerSystemLoad();
        } catch (Exception e) {
            log.error(e.getMessage());
            // 不做处理,继续运行
        }
    }
}

  

 2.2 定义配置类,其中声明定时任务Bean

package com.yc.dudu.common.monitor;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * 服务器负载监控自动配置类
 *
 * @author zhya
 * @date 2018/09/20
 **/
@Configuration
public class ServerLoadMonitorAutoConfig {
    /**
     * 是否开启监控配置参数
     */
    @Value("${monitor.server.enabled:}")
    private String enabledConfig;

    /**
     * 错误提醒
     */
    @PostConstruct
    protected void init() {
        if (StringUtils.isBlank(enabledConfig)) {
            System.err.println("~~~Please config the monitor.server.enabled property in application.yml file to enable server monitor function~~~");
        }
    }

    /**
     * 根据运行环境决定是否开启服务器负载信息监控
     *
     * @return
     */
    @Bean
    @ConditionalOnProperty(prefix = "monitor.server", name = "enabled", havingValue = "true")
    protected ServerLoadMonitorRunner startServerMonitor() {
        return new ServerLoadMonitorRunner();
    }
}

 

2.3 定义自己的Enable注解,Import 配置类

package com.yc.dudu.common.monitor;

import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/**
 * 服务器负载监控开启注解
 *
 * @author zhya
 * @date 2018/09/20
 **/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ServerLoadMonitorAutoConfig.class)
@Documented
@Inherited
public @interface EnableServerLoadMonitor {
}

2.4 使用自定义的EnableServerLoadMonitor注解,配合着配置参数,就可以开启服务器负载监控功能了

package com.yc.dudu.gate.admin;

import com.yc.dudu.auth.client.EnableDuduAuthClient;
import com.yc.dudu.common.monitor.EnableServerLoadMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import zipkin2.Span;
import zipkin2.reporter.Reporter;

/**
 * admin网关启动类
 *
 * @author zhya
 * @date 2018/9/20
 **/
@EnableHystrix
@EnableServerLoadMonitor
@SpringBootApplication
@EnableDiscoveryClient
@EnableDuduAuthClient
@EnableFeignClients({"com.yc.dudu.auth.client.feign", "com.yc.dudu.gate.admin.feign"})
public class AdminGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminGatewayApplication.class, args);
        System.out.println("AdminGatewayApplication is started!~~~~~~~~");
    }

    /**
     * 链路跟踪信息输出log
     */
    private static Logger sleuthLog = LoggerFactory.getLogger("sleuthLog");

    /**
     * 将链路跟踪信息输出到日志文件
     *
     * @return
     */
    @Bean
    public Reporter<Span> spanReporter() {
        Reporter<Span> reporter = span -> sleuthLog.info(span.toString());
        return reporter;
    }
}

  

posted @ 2018-10-25 09:50  zhya_hopeful  阅读(5626)  评论(2编辑  收藏  举报