最近在看国内比较优秀的分布式调度框架xxl-job的源码,作者使用了比较多的spring4版本后提供的便捷方法,正好自己工作中有用到xxl-job,就顺带研究下。

xxl-job相关的代码就不细讲了,重点讲下MethodIntrospector这个工具类的使用场景。

先看下源码中的注释:

/*** Defines the algorithm for searching for metadata-associated methods exhaustively* including interfaces and parent classes while also dealing with parameterized methods* as well as common scenarios encountered with interface and class-based proxies.** <p>Typically, but not necessarily, used for finding annotated handler methods.** @author Juergen Hoeller* @author Rossen Stoyanchev* @since 4.2.3*/

大概的意思是,定义了查找指定方法的一些算法,主要可以被用来查找有指定注解的方法

核心方法 selectMethods

 /*** Select methods on the given target type based on the lookup of associated metadata.* <p>Callers define methods of interest through the {@link MetadataLookup} parameter,* allowing to collect the associated metadata into the result map.* @param targetType the target type to search methods on* @param metadataLookup a {@link MetadataLookup} callback to inspect methods of interest,* returning non-null metadata to be associated with a given method if there is a match,* or {@code null} for no match* @return the selected methods associated with their metadata (in the order of retrieval),* or an empty map in case of no match*/public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) {final Map<Method, T> methodMap = new LinkedHashMap<>();Set<Class<?>> handlerTypes = new LinkedHashSet<>();Class<?> specificHandlerType = null;//判断是否是代理类if (!Proxy.isProxyClass(targetType)) {//如果是代理类,找到实际的类型specificHandlerType = ClassUtils.getUserClass(targetType);handlerTypes.add(specificHandlerType);}handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType));//遍历所有找到的class对象for (Class<?> currentHandlerType : handlerTypes) {final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);ReflectionUtils.doWithMethods(currentHandlerType, method -> {//获取指定的methodMethod specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);//获取方法关联的元数据,一般是指注解T result = metadataLookup.inspect(specificMethod);if (result != null) {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) {methodMap.put(specificMethod, result);}}}, ReflectionUtils.USER_DECLARED_METHODS);}return methodMap;}

MetadataLookup接口

 /*** A callback interface for metadata lookup on a given method.* @param <T> the type of metadata returned*/@FunctionalInterfacepublic interface MetadataLookup<T> {/*** Perform a lookup on the given method and return associated metadata, if any.* @param method the method to inspect* @return non-null metadata to be associated with a method if there is a match,* or {@code null} for no match*/@NullableT inspect(Method method);}

这样看可能有点抽象,来个实际点的例子

定义一个自定义的注解:

package cn.magicnian.annotation;import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MagicAround {String value();Class[] releationClazz();
}

然后写一个简单的使用场景:

package cn.magicnian.annotation;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Component
public class MyMagicAroudTest {private Logger logger = LoggerFactory.getLogger(MyMagicAroudTest.class);@MagicAround(value = "function1",releationClazz = String.class)public String function1(String key) {logger.info("......pring key:{}......", key);return "success";}
}

使用MethondIntrospector处理

package cn.magicnian.annotation;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.Map;@Component
public class AnnotationMethondExecutor implements ApplicationContextAware, SmartInitializingSingleton {private static final Logger logger = LoggerFactory.getLogger(AnnotationMethondExecutor.class);private ApplicationContext applicationContext;@Overridepublic void afterSingletonsInstantiated() {String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true);for (String beanDefinitionName : beanDefinitionNames) {Object bean = applicationContext.getBean(beanDefinitionName);// referred to :org.springframework.context.event.EventListenerMethodProcessor.processBeanMap<Method, MagicAround> annotatedMethods = null;try {annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(),new MethodIntrospector.MetadataLookup<MagicAround>() {@Overridepublic MagicAround inspect(Method method) {return AnnotatedElementUtils.findMergedAnnotation(method, MagicAround.class);}});} catch (Throwable ex) {logger.error("MagicAround resolve error for bean [{}]. exception : {}", beanDefinitionName, ex);}if (annotatedMethods == null || annotatedMethods.isEmpty()) {continue;}for (Map.Entry<Method, MagicAround> methodMagicAroundEntry : annotatedMethods.entrySet()) {Method method = methodMagicAroundEntry.getKey();MagicAround magicAround = methodMagicAroundEntry.getValue();if (magicAround == null) {continue;}String name = magicAround.value();if (name.trim().length() == 0) {throw new RuntimeException("magicaround name invalide, for[" + bean.getClass() + "#" + method.getName() + "] .");}method.setAccessible(true);try {//执行该方法Object returnValue = method.invoke(bean, new Object[]{"magicnian"});logger.info("returnValue : {}", returnValue);} catch (Exception e) {e.printStackTrace();}}}}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}

看下执行结果:

可以看到,在AnnotationMethodExecutor中顺利的找到了标记有MagicAround注解的方法,并且执行了该方法

分割线


欢迎关注我的个人公众号,新人有研发资源分享,定期推出高质量的技术文章

MethodIntrospector工具类使用相关推荐

  1. java日期转化工具类

    package com.rest.ful.utils;import java.text.DateFormat; import java.text.ParseException; import java ...

  2. java数据类型相互转换工具类

    package com.rest.ful.utils;import java.util.ArrayList; import java.util.HashMap; import java.util.Li ...

  3. 客快物流大数据项目(五十六): 编写SparkSession对象工具类

    编写SparkSession对象工具类 后续业务开发过程中,每个子业务(kudu.es.clickhouse等等)都会创建SparkSession对象,以及初始化开发环境,因此将环境初始化操作封装成工 ...

  4. [JAVA EE] Thymeleaf 常用工具类

    Thymeleaf 提供了丰富的表达式工具类,例如: #strings:字符串工具类 #dates:时间操作和时间格式化 #numbers:格式化数字对象的方法 #bools:常用的布尔方法 #str ...

  5. httpclient工具类,post请求发送json字符串参数,中文乱码处理

    在使用httpclient发送post请求的时候,接收端中文乱码问题解决. 正文: 我们都知道,一般情况下使用post请求是不会出现中文乱码的.可是在使用httpclient发送post请求报文含中文 ...

  6. spring boot 文件上传工具类(bug 已修改)

    以前的文件上传都是之前前辈写的,现在自己来写一个,大家可以看看,有什么问题可以在评论中提出来. 写的这个文件上传是在spring boot 2.0中测试的,测试了,可以正常上传,下面贴代码 第一步:引 ...

  7. SharePreference工具类

    安卓开发一般都需要进行数据缓存,常用操作老司机已为你封装完毕,经常有小伙伴问怎么判断缓存是否可用,那我告诉你,你可以用这份工具进行存储和查询,具体可以查看源码,现在为你开车,Demo传送门. 站点 S ...

  8. java录排名怎么写_面试官:Java排名靠前的工具类你都用过哪些?

    你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 推荐:https://www.xttblog.com/?p=5158 在Java ...

  9. 【转】 Android快速开发系列 10个常用工具类 -- 不错

    原文网址:http://blog.csdn.net/lmj623565791/article/details/38965311 转载请标明出处:http://blog.csdn.net/lmj6235 ...

最新文章

  1. Java 面向对象细节
  2. java图形用户界面概述_Java中图形用户界面概述
  3. SpirngMVC通过Ajax传递多个对象
  4. 我摸鱼写的Java片段意外称霸Stack Overflow十年、征服6000多GitHub开源项目: 有bug!...
  5. 中文字符频率统计python_使用 Python 统计中文字符的数量
  6. mysql删除用户密码_MySQL 创建用户、授权用户、撤销用户权限、更改用户密码、删除用户(实用技巧)...
  7. Tushare使用分享
  8. 【论文泛读05】基于Conv-LSTM的短期交通流预测
  9. 22. SCHEMA_PRIVILEGES
  10. PhpStorm2017破解版
  11. Variational Autoencoders and Nonlinear ICA: A Unifying Framework
  12. 【海思篇】【Hi3516DV300】六、音频输入篇
  13. Q版京剧脸谱来喽——武生
  14. BigDecimal用法之计算等额本金和等额本息
  15. python 网络爬虫
  16. xms应用框架 - 基于.netcore
  17. 【matlab教程】02、拼接矩阵或向量
  18. 花旗金融技术岗社招内推
  19. 51nod1299 监狱逃离 最小割
  20. 工具篇——1、TMUX

热门文章

  1. 深度学习实战-图像风格迁移
  2. 双分支定向耦合器 HFSS仿真
  3. 计算机组装与维护双系统安装,给你的电脑安装一个不可见的WINPE救援系统(独立启动双系统)...
  4. selenium web录制(selenium_ide-2.9.1-fx.xpi和老版本火狐浏览器在最下方)
  5. _pickle.UnpicklingError: unpickling stack underflow
  6. 联想小新 mini 主机 评测
  7. 原来棒棒糖还有这功能~
  8. Google MLOps白皮书:MLOps实践者指南Part I MLOps生命周期及核心能力
  9. sit是什么环境_测试环境是什么_搭建测试环境要遵循什么原则?
  10. excel 表格怎么让内容回车换行?