SpringBoot 自定义注解的增强使用方式,动态调用指定方法

摘要:我们平常使用自定义注解大多数都是配合AOP来使用的,本文给大家带来其他的使用方式,可做到无侵入式动态调用指定的方法;更复杂的使用方式自己挖掘。

案例简要说明

按照前端传入的参数,后端动态调用打印方法来执行实际的逻辑

编码

定义注解

less 复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Print {

    String value();

}

扫描注解的方法

CommandLineRunner是在服务启动完成后再执行任务,该案例是调用不传参的方法,如果传参则需要定义好,否则反射调用会报错。

typescript 复制代码
@Slf4j
@Component
public class PrintContextHandler implements CommandLineRunner {

    @Autowired
    private ApplicationContext applicationContext;

    private Map<String,Runnable> printMethodMap = new HashMap<>();

    @Override
    public void run(String... args) throws Exception {
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Component.class);
        beans.putAll(applicationContext.getBeansWithAnnotation(Service.class));
        for (Object bean : beans.values()) {
            Method[] methods = bean.getClass().getDeclaredMethods();
            for (Method method : methods) {
                Print print = AnnotationUtils.findAnnotation(method, Print.class);
                if (print != null) {
                    Runnable runnable = new Runnable() {
                        @Override
                        public void run() {
                            try{
                                method.invoke(bean);
                            }catch (Exception ex){
                                log.error("print执行失败",ex);
                            }
                        }
                    };
                    printMethodMap.put(print.value(), runnable);
                }
            }
        }

    }

    /**
     * 执行
     * @param key
     * @return
     */
    public Object doPrint(String key){
        Runnable runnable = printMethodMap.get(key);
        if(null != runnable){
            runnable.run();
        }
        return "SUCCESS";
    }



}

定义注解的方法

typescript 复制代码
@Slf4j
@Service
public class InPrintService {

    @Print(value = "inPrint01")
    public String inPrint01(){
        log.info("inPrint01");
        return "inPrint01";
    }

    @Print(value = "inPrint02")
    public String inPrint02(){
        log.info("inPrint02,param1=");
        return "inPrint02";
    }
}
  • 方法2
less 复制代码
@Slf4j
@Service
public class OutPrintService {

    @Print(value = "outPrint01")
    public String outPrint01(){
        log.info("outPrint01");
        return "outPrint01";
    }

}

控制器

less 复制代码
@RequestMapping(value = "print")
@RestController
public class PrintController {

    @Autowired
    private PrintContextHandler printContextHandler;

    @GetMapping(value = "testPrintAnno")
    public Object testPrintAnno(String key){
        return printContextHandler.doPrint(key);
    }

}

测试结果

相关推荐
数据小馒头1 分钟前
浅谈SQL审核(一):SQL审核实现方式与常见工具的选择
后端
武子康32 分钟前
大数据-128 - Flink 并行度详解:从概念到最佳实践,一文读懂任务并行执行机制 代码示例与性能优化
大数据·后端·flink
Q_Q51100828535 分钟前
python+uniapp基于微信小程序的学院设备报修系统
spring boot·python·微信小程序·django·flask·uni-app
小毛驴8501 小时前
在Spring Boot开发中,HEAD、OPTIONS和 TRACE这些HTTP方法各有其特定的应用场景和实现方式
spring boot·后端·http
Jabes.yang1 小时前
Java面试大作战:从缓存技术到音视频场景的探讨
java·spring boot·redis·缓存·kafka·spring security·oauth2
zl9798991 小时前
SpringBoot-依赖管理和自动配置
spring boot·后端·状态模式
JaguarJack1 小时前
PHP8.5 的新 URI 扩展
后端·php
绝无仅有1 小时前
面试真实经历某商银行大厂数据库MYSQL问题和答案总结(一)
后端·面试·github
绝无仅有1 小时前
Docker 实战经验之关键文件误删恢复指南
后端·面试·github
paopaokaka_luck1 小时前
基于SpringBoot+Vue的数码交流管理系统(AI问答、协同过滤算法、websocket实时聊天、Echarts图形化分析)
vue.js·人工智能·spring boot·websocket·echarts