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

}

测试结果

相关推荐
计算机毕设VX:Fegn08957 小时前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
没差c8 小时前
springboot集成flyway
java·spring boot·后端
三水不滴8 小时前
Redis 过期删除与内存淘汰机制
数据库·经验分享·redis·笔记·后端·缓存
编程彩机9 小时前
互联网大厂Java面试:从Java SE到大数据场景的技术深度解析
java·大数据·spring boot·面试·spark·java se·互联网大厂
笨蛋不要掉眼泪9 小时前
Spring Boot集成LangChain4j:与大模型对话的极速入门
java·人工智能·后端·spring·langchain
像少年啦飞驰点、10 小时前
零基础入门 Spring Boot:从“Hello World”到可上线微服务的完整学习指南
java·spring boot·微服务·编程入门·后端开发
indexsunny11 小时前
互联网大厂Java面试实战:从Spring Boot到微服务架构的技术问答解析
java·spring boot·redis·微服务·kafka·jwt·flyway
sheji341611 小时前
【开题答辩全过程】以 基于SpringBoot的疗养院管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
短剑重铸之日12 小时前
《设计模式》第六篇:装饰器模式
java·后端·设计模式·装饰器模式