扫描项目中所有包含某注解的方法及获取其URI

本文介绍如何在SpringBoot应用中通过注解扫描获取所有包含特定注解的方法及其URI,利用ApplicationRunner在容器启动时执行扫描,适用于动态配置或日志记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

获取到包含某注解的所有类

首先先要获取到applicationContext
只要类 implements ApplicationContextAware就会自动注入到类里的applicationContext
话不多说直接上代码

@Component
@Slf4j
public class test implements ApplicationContextAware {

	private static ApplicationContext applicationContext;
	
	public void test(Class<? extends Annotation> annotation){
		List<Class<?>> inClassList = new ArrayList<>();
		Map<Class<?>, Set<Method>> containsMap = new HashMap<>();
		//获取到所有包含@RestController 或者 @Controller的bean
		Map<String, Object> beanList = applicationContext.getBeansWithAnnotation(RestController.class);
		beanList.putAll(applicationContext.getBeansWithAnnotation(Controller.class));
		beanList.forEach((k, v) -> inClassList.add(applicationContext.getType(k)));
		getClassesWithAnnotationFromAllClasses(inClassList, annotation,  containsMap);
	}
}

inClassList里就可以获取到所有的包含@RestController 或者 @Controller 的bean了

获取类集合里所有包含自定义注解的方法名

/**
     * 获取类里所有包含annotation的方法名
     *
     * @param inClassList  需过滤其中方法的class集合
     * @param annotation   注解class
     * @param map          包含该annotation的map,key为controller类,集合中为方法
     */
    private void getMethodsWithAnnotationFromAllClasses(List<Class<?>> inClassList,
                                                        Class<? extends Annotation> annotation, Map<Class<?>, Set<Method>> map) {
        for (Class<?> myClasss : inClassList) {
            Method[] methods = myClasss.getMethods();
            Set<Method> methodList = new HashSet<>();
            for (Method method : methods) {
            //findAnnotation也可以拿到其父类是否包含该注解
                if (null != method && null != AnnotationUtils.findAnnotation(method, annotation)) {
                    try {
                        methodList.add(method);
                    }catch (Exception e){
                        log.error(e.toString());
                    }
                }
            }

            if (methodList.size() > 0) {
                map.put(myClasss, methodList);
            }

        }

获取所有包含某注解的方法及获取其URI

最后一步就是获取方法的URI了,直接把完整的代码贴出来

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;


@Component
@Slf4j
public class test implements ApplicationContextAware {

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    private static ApplicationContext applicationContext;

    public Set<String[]> test(Class<? extends Annotation> annotation) {
        List<Class<?>> inClassList = new ArrayList<>();
        Map<Class<?>, Set<Method>> containsMap = new HashMap<>();
        //获取到所有包含@RestController 或者 @Controller的bean
        Map<String, Object> beanList = applicationContext.getBeansWithAnnotation(RestController.class);
        beanList.putAll(applicationContext.getBeansWithAnnotation(Controller.class));
        beanList.forEach((k, v) -> inClassList.add(applicationContext.getType(k)));
        getMethodsWithAnnotationFromAllClasses(inClassList, annotation, containsMap);
        Set<String[]> resultList = new HashSet<>();
        //获取所有uri的集合
        Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : map.entrySet()) {
            HandlerMethod method = entry.getValue();
            for (Map.Entry<Class<?>, Set<Method>> classEntry : containsMap.entrySet()) {
                Set<Method> str = classEntry.getValue();
                Set<String> methodNameSet = str.stream().map(Method::getName).collect(Collectors.toSet());
                //如果controller匹配到了containsMap的key且方法存在于containsMap的value里,将其uri加入resultList
                String controllerName = classEntry.getKey().getName();
                String methodName = method.getBeanType().getName();
                //controllerName拿到的是代理beanName,需要处理
                if (controllerName.contains("$$")) {
                    controllerName = controllerName.substring(0, controllerName.indexOf("$$"));
                }
                try {
                    if (controllerName.equals(methodName) && methodNameSet.contains(method.getMethod().getName())) {
                        //获取uri
                        for (RequestMethod m : entry.getKey().getMethodsCondition().getMethods()) {
                            for (String pattern : entry.getKey().getPatternsCondition().getPatterns()) {
                                String[] resultArr = new String[2];
                                resultArr[0] = m.name();
                                resultArr[1] = pattern;
                                resultList.add(resultArr);
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error(e.toString());
                }
            }
        }
        return resultList;
    }

    /**
     * 获取类里所有包含annotation的方法名
     *
     * @param inClassList 需过滤其中方法的class集合
     * @param annotation  注解class
     * @param map         包含该annotation的map,key为controller类,集合中为方法
     */
    private void getMethodsWithAnnotationFromAllClasses(List<Class<?>> inClassList,
                                                        Class<? extends Annotation> annotation, Map<Class<?>, Set<Method>> map) {
        for (Class<?> myClasss : inClassList) {
            Method[] methods = myClasss.getMethods();
            Set<Method> methodList = new HashSet<>();
            for (Method method : methods) {
                //findAnnotation也可以拿到其父类是否包含该注解
                if (null != method && null != AnnotationUtils.findAnnotation(method, annotation)) {
                    try {
                        methodList.add(method);
                    } catch (Exception e) {
                        log.error(e.toString());
                    }
                }
            }

            if (methodList.size() > 0) {
                map.put(myClasss, methodList);
            }

        }

    }
}

使用ApplicationRunner以在容器启动完成的时候获取列表

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class ServiceStarted implements ApplicationRunner {
    @Autowired
    Test test;
    @Override
    public void run(ApplicationArguments args){
        Set<String[]> sets = test.test(TestAnnotation.class);
        log.info("获取到列表{}",sets);
        //dosomething
    }
}

拿到列表后就可以dosomething了,保存到本地文件夹、保存至redis、或者也可以在这一步进行对类操作,都可以
set[0] 为method 即 POST GET DELETE
set [1] 为该方法的uri

Spring Boot是一个流行的Java框架,它简化了构建生产级Spring应用程序的过程。其中包含了许多内置的注解,这些注解有助于配置和管理应用程序。以下是Spring Boot中一些常见的注解: 1. `@SpringBootApplication`: 这是整合了`@SpringBootConfiguration`、`@EnableAutoConfiguration`和`@ComponentScan`三个注解的总和,用于标记一个类作为Spring Boot应用的起点,它会自动配置Spring应用并进行组件扫描。 2. `@RestController`: 用于标记一个类为RESTful控制器,其方法直接处理HTTP请求,返回HTTP响应,常配合`@GetMapping`、`@PostMapping`等其他HTTP方法注解使用。 3. `@RequestMapping`: 用于定义处理HTTP请求的方法URL映射,如`@GetMapping`(处理GET请求)、`@PostMapping`(处理POST请求)等。 4. `@Autowired`: 标记依赖注入,告诉Spring自动将属性设置为其他组件的实例。 5. `@PathVariable`: 用于在HTTP请求的URI中解析变量,通常与REST控制器方法一起使用。 6. `@RequestBody`: 当处理表单数据或JSON请求体时,这个注解表示方法参数应从请求体中获取。 7. `@ResponseBody`: 用于将方法的返回值转换为HTTP响应体内容,常用于RESTful API的输出。 8. `@ComponentScan`: 指定哪些包下的组件应该被Spring IoC容器扫描并注册。 9. `@Service`, `@Repository`, `@Controller`, `@Component`: 分别用于标记业务层、持久层、控制层和自定义组件,它们都用于自动装配到Spring IoC容器中。 10. `@Transactional`: 控制事务管理,标记为该方法的事务处理。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值