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 小时前
限流、控并发、减GC!一文搞懂Go项目资源优化的正确姿势
后端·google·go
好奇的菜鸟5 小时前
Spring Boot 事务失效问题:同一个 Service 类中方法调用导致事务失效的原因及解决方案
数据库·spring boot·sql
来自宇宙的曹先生6 小时前
视频网站弹幕系统简易实现
spring boot·音视频
姑苏洛言7 小时前
编写产品需求文档:黄历日历小程序
前端·javascript·后端
姑苏洛言8 小时前
搭建一款结合传统黄历功能的日历小程序
前端·javascript·后端
你的人类朋友8 小时前
🍃认识一下boomi
后端
苏三说技术8 小时前
MySQL的三大日志
后端
豌豆花下猫8 小时前
让 Python 代码飙升330倍:从入门到精通的四种性能优化实践
后端·python·ai
南雨北斗9 小时前
TP6使用PHPMailer发送邮件
后端
你的人类朋友9 小时前
🤔什么时候用BFF架构?
前端·javascript·后端