SpringBoot整合策略模式之基于 ApplicationContextAware + 枚举类 + 自定义注解实现(推荐)

1、ILog

package com.atguigu.design.demo.spring;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public interface ILog {

    void log(String msg);

    //LogType getType();
}
@BeanLogType(LogType.FILE_LOG)
class FileLog implements ILog {
    @Override
    public void log(String msg) {
        System.out.println("输出日志到文件:"  + msg);
    }

    /*
    @Override
    public LogType getType() {
        return LogType.FILE_LOG;
    }
    */
}
@BeanLogType(LogType.CONSOLE_LOG)
class ConsoleLog implements ILog {
    @Override
    public void log(String msg) {
        System.out.println("输出日志到控制台:" + msg);
    }

    /*
    @Override
    public LogType getType() {
        return LogType.CONSOLE_LOG;
    }
    */
}
@Component
class LogClient implements ApplicationContextAware {

    private static final Map<String, ILog> MAP = new ConcurrentHashMap<>();

    /*
    @Autowired
    private FileLog fileLog;

    @Autowired
    private ConsoleLog consoleLog;

    @PostConstruct
    public void init() {
        MAP.put("1", fileLog);
        MAP.put("2", consoleLog);
    }
    */

    /**
     * 根据类型记录日志信息
     *
     * @param type 日志类型,用于区分不同类型的日志
     * @param msg 待记录的消息
     */
    public void log(String type, String msg) {
        MAP.get(type).log(msg);
    }

    /**
     * 重写setApplicationContext方法,用于初始化带有BeanLogType注解的bean
     * 这个方法的目的是在Spring上下文加载时,获取所有带有BeanLogType注解的bean,并根据注解中的logType类型进行分类存储
     *
     * @param applicationContext Spring应用上下文,用于获取所有带有BeanLogType注解的bean
     * @throws BeansException 如果bean的获取过程中发生异常
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取所有带有BeanLogType注解的bean
        Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(BeanLogType.class);

        // 如果没有找到带有BeanLogType注解的bean,则直接返回
        if (CollectionUtils.isEmpty(beanMap)) {
            return;
        }

        // 提取所有带有BeanLogType注解的bean
        Collection<Object> beans = beanMap.values();

        // 遍历每个bean,根据其上的BeanLogType注解中的value值(LogType类型),将bean按照类型存储到MAP静态变量中
        // 这里的MAP是一个将LogType类型与bean实例(必须实现ILog接口)映射的全局映射表
        beans.forEach(bean -> {
            LogType logType = bean.getClass().getAnnotation(BeanLogType.class).value();
            MAP.put(logType.type, (ILog) bean);
        });
    }

    /**
     * 设置应用上下文,用于初始化日志策略
     * 该方法通过应用上下文获取所有类型的日志策略,并将其初始化
     *
     * @param applicationContext 应用上下文
     * @throws BeansException 如果无法从应用上下文中获取日志策略,抛出该异常
     */
    /*
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取所有实现ILog接口的Bean
        Map<String, ILog> beansOfType = applicationContext.getBeansOfType(ILog.class);
        // 如果没有找到任何ILog实现,则直接返回
        if (CollectionUtils.isEmpty(beansOfType)) {
            return;
        }
        // 将Map中的值转换为Collection类型
        Collection<ILog> beans = beansOfType.values();

        // 遍历所有日志策略Bean,将它们按照类型添加到MAP中
        beans.forEach(bean->{
            // 获取日志策略的类型
            LogType type = bean.getType();
            // 将日志策略添加到MAP中,以便后续根据类型获取对应的日志策略
            MAP.put(type.type, bean);
        });
    }
    */
}

2、LogType 枚举类

package com.atguigu.design.demo.spring;
public enum LogType {
    FILE_LOG("1","文件日志"),
    CONSOLE_LOG("2","控制台日志")
    ;

    public String type;
    public String desc;

    LogType(String type, String desc) {
        this.type = type;
        this.desc = desc;
    }
}

3、@BeanLogType 注解

package com.atguigu.design.demo.spring;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface BeanLogType {

    LogType value();
}

4、DemoController

package com.atguigu.design.demo.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
    @Autowired
    private LogClient logClient;

    @GetMapping("log/{type}")
    public String log(@PathVariable String type, @RequestParam("msg") String msg) {
        logClient.log(type, msg);
        return "日志输出成功!";
    }
}

5、application.properties

spring.application.name=design-demo
server.port=10010

6、DesignDemoApplication

package com.atguigu.design.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


// Generated by https://start.springboot.io
// 优质的 spring/boot/data/security/cloud 框架中文文档尽在 => https://springdoc.cn
@SpringBootApplication
public class DesignDemoApplication {

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

}

在这里插入图片描述

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值