springboot 获取所有带指定标签的方法

之前有一个需求 写一个自定义注解,然后在项目启动以后获取到所有带自定义注解的方法,然后进行业务分析,查了很多资料,但发现很多不全面,所以自己记录一下

实现ApplicationContextAware和ApplicationListener

之所以ApplicationContextAware和ApplicationListener都需要实现是因为我发现有时候只实现其中一个无法得到想要的结果,接下来细说。

public class TestListener implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {

    private ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        getAnnotationMap(applicationContext);
    }
}

通过重写setApplicationContext方法获取applicationContext以便之后获取相关bean。
之前由博客说可以在重写onApplicationEvent方法中通过ContextRefreshedEvent 获得root节点的applicationContext,但是我试过之后在我的情境中无法获得root节点,可能和项目环境有关。

 public void onApplicationEvent(ContextRefreshedEvent event) {  
        // 根容器为Spring容器  
        if(event.getApplicationContext().getParent()==null){  
            Map<String,Object> beans = event.getApplicationContext().getBeansWithAnnotation(IMobile.class);  
            for(Object bean:beans.values()){  
                System.err.println(bean==null?"null":bean.getClass().getName());  
            }  
            System.err.println("=====ContextRefreshedEvent====="+event.getSource().getClass().getName());  
        }  
 }  

因为ApplicationContextAware的setApplicationContext方法不一定是在所有bean初始化完成后实现的,所以我在onApplicationEvent方法中调用自定义方法,确保此时所有bean都已经初始化完毕。

通过反射获取具体注解

获取到bean以后可以通过反射获取class对象来获取指定注解

Class<?> clazz = bean.getClass();
Method[] ms = clazz.getMethods();
for(Method m:ms){   
 Service service= m.getAnnotation(Service.class);
}

但是这样会有一个问题,因为当bean被代理后,像是加了事务,此时获取到的class是代理类,无法获得到源类上的注解属性,所以获得注解的为空
此时需要使用aop工具类进行class文件获取

Class clazz = AopUtils.getTargetClass(value);
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);

这样获取到class对象和method方法对象中都可以拿到源类上的注解属性。

整体代码

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Map;

public class TestListener implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {

    private ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        getAnnotationMap(applicationContext);
    }

    public void getAnnotationMap(ApplicationContext applicationContext) {
        Map<String, Object> beansWithAnnotationMap = this.applicationContext.
                getBeansWithAnnotation(Service.class);

        beansWithAnnotationMap.values().forEach(value -> {
            Class clazz = AopUtils.getTargetClass(value);
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method:methods){
                if(method.isAnnotationPresent(Service.class)) {
                    Service service = method.getAnnotation(Service.class);
                    // 业务操作
                }
            }
        });
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值