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);
    }

}

测试结果

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
大勇前进2 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
vipxieliang2 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
yuzhi_liu2 天前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端
alsmile2 天前
Node-RED 之外,国产规则引擎的新方案:基于标准语法,Go 先行实现
后端·开源·go
大白802 天前
PHP 内存溢出排查思路:看懂报错日志,精准定位问题
后端
二月龙2 天前
PHP 接口返回统一响应封装,让前后端对接更省心
后端