MethodIntrospector工具类使用
最近在看国内比较优秀的分布式调度框架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工具类使用相关推荐
- java日期转化工具类
package com.rest.ful.utils;import java.text.DateFormat; import java.text.ParseException; import java ...
- java数据类型相互转换工具类
package com.rest.ful.utils;import java.util.ArrayList; import java.util.HashMap; import java.util.Li ...
- 客快物流大数据项目(五十六): 编写SparkSession对象工具类
编写SparkSession对象工具类 后续业务开发过程中,每个子业务(kudu.es.clickhouse等等)都会创建SparkSession对象,以及初始化开发环境,因此将环境初始化操作封装成工 ...
- [JAVA EE] Thymeleaf 常用工具类
Thymeleaf 提供了丰富的表达式工具类,例如: #strings:字符串工具类 #dates:时间操作和时间格式化 #numbers:格式化数字对象的方法 #bools:常用的布尔方法 #str ...
- httpclient工具类,post请求发送json字符串参数,中文乱码处理
在使用httpclient发送post请求的时候,接收端中文乱码问题解决. 正文: 我们都知道,一般情况下使用post请求是不会出现中文乱码的.可是在使用httpclient发送post请求报文含中文 ...
- spring boot 文件上传工具类(bug 已修改)
以前的文件上传都是之前前辈写的,现在自己来写一个,大家可以看看,有什么问题可以在评论中提出来. 写的这个文件上传是在spring boot 2.0中测试的,测试了,可以正常上传,下面贴代码 第一步:引 ...
- SharePreference工具类
安卓开发一般都需要进行数据缓存,常用操作老司机已为你封装完毕,经常有小伙伴问怎么判断缓存是否可用,那我告诉你,你可以用这份工具进行存储和查询,具体可以查看源码,现在为你开车,Demo传送门. 站点 S ...
- java录排名怎么写_面试官:Java排名靠前的工具类你都用过哪些?
你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 推荐:https://www.xttblog.com/?p=5158 在Java ...
- 【转】 Android快速开发系列 10个常用工具类 -- 不错
原文网址:http://blog.csdn.net/lmj623565791/article/details/38965311 转载请标明出处:http://blog.csdn.net/lmj6235 ...
最新文章
- Java 面向对象细节
- java图形用户界面概述_Java中图形用户界面概述
- SpirngMVC通过Ajax传递多个对象
- 我摸鱼写的Java片段意外称霸Stack Overflow十年、征服6000多GitHub开源项目: 有bug!...
- 中文字符频率统计python_使用 Python 统计中文字符的数量
- mysql删除用户密码_MySQL 创建用户、授权用户、撤销用户权限、更改用户密码、删除用户(实用技巧)...
- Tushare使用分享
- 【论文泛读05】基于Conv-LSTM的短期交通流预测
- 22.	SCHEMA_PRIVILEGES
- PhpStorm2017破解版
- Variational Autoencoders and Nonlinear ICA: A Unifying Framework
- 【海思篇】【Hi3516DV300】六、音频输入篇
- Q版京剧脸谱来喽——武生
- BigDecimal用法之计算等额本金和等额本息
- python 网络爬虫
- xms应用框架 - 基于.netcore
- 【matlab教程】02、拼接矩阵或向量
- 花旗金融技术岗社招内推
- 51nod1299 监狱逃离 最小割
- 工具篇——1、TMUX
热门文章
- 深度学习实战-图像风格迁移
- 双分支定向耦合器 HFSS仿真
- 计算机组装与维护双系统安装,给你的电脑安装一个不可见的WINPE救援系统(独立启动双系统)...
- selenium web录制(selenium_ide-2.9.1-fx.xpi和老版本火狐浏览器在最下方)
- _pickle.UnpicklingError: unpickling stack underflow
- 联想小新 mini 主机 评测
- 原来棒棒糖还有这功能~
- Google MLOps白皮书:MLOps实践者指南Part I MLOps生命周期及核心能力
- sit是什么环境_测试环境是什么_搭建测试环境要遵循什么原则?
- excel 表格怎么让内容回车换行?