问题背景:由于任务管理模块的线程中需要调用其它模块中已经实现的方法,需要通过反射机制找到其它模块中指定注解下的方法。
1、定义一个在类上的自定义注解
@Target(ElementType.TYPE) // 此注解使用在类上
@Retention(RetentionPolicy.RUNTIME) // 在运行阶段可以被反射机制获取
@Component // 自定义注解在项目启动时可以被加载到容器中
public @interface MyClassAnnotation{
}
2、定义一个在方法上的自定义注解
@Target(ElementType.METHOD) // 此注解使用在类上
@Retention(RetentionPolicy.RUNTIME) // 在运行阶段可以被反射机制获取
@Component // 自定义注解在项目启动时可以被加载到容器中
public @interface MyMethodAnnotation{
}
3、在自定义类、自定义方法上加上自定义注解
@MyClassAnnotation
public class AnnotationTest {
@MyMethodANnotation
public void targetMethod() {
System.out.println("目标方法被执行了!");
}
}
4、在需要的地方调用targetMethod()方法,例如线程的run()方法中
// 获取指定注解修饰的beans对象集合
// 返回一个被注解表示的bean的Map对象,bean的names作为key,与name对应的实例做为值
Map<String, Object> beansWithAnnotation = SpringUtil.getApplicationContext().getBeansWithAnnotation(MyClassAnnotation.class);
Iterator entries = beansWithAnnotation.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry next = (Map.Entry) entries.next();
System.out.println("key == " + next.getKey()); // key == antotionTest;这只是对象的名字,不是实例化的对象
System.out.println("value == " + next.getValue()); // value == com.自己的包名.AnnotationTest@7ee3bf66
// 获取类下所有的方法,包括private和protected修饰的
Method[] declaredMethods = next.getValue().getClass().getDeclaredMethods();
for (Method method : declaredMethods) {
// 判断方法上是否有指定注解
if (method.isAnnotionPresent(MyMethodAnnotation.class)) {
System.out.println(method.getName());
// 能够运行被private、protected修饰的方法
ReflectionUtils.makeAccessible(method);
// 执行其它模块中想要调用的方法(包括被static修饰)
// getClass()是返回Class类型的对象
// newInstance()是通过对应类的无参构造方法获取类的实例化对象
method.invoke(next.getValue().getClass().newInstance());
// 如果调用的方法为static修饰的静态方法,使用以下代码即可
// method.invoke(next.getValue());
// 补充:如果自定义注解中有某个属性,例如:userName(),获取该属性的方法为
// method.getAnnotation(MyMethodAnnotation.class).userName();
}
}
}