如何使用代码隐藏创建自定义批注

我想创建自己的自定义注释。我的框架是独立的Java应用程序。当有人注释他的 pojo 类时,后面的“隐藏”代码将触发方法。

例如,今天在Java EE中,我们有注释。当您使用 MessageListener 接口对类进行批注并另外实现时,会有一个隐藏代码将触发 。当消息从队列/主题到达时。@MessageDriven@MessageDrivenonMessage(Message msg)

我如何创建可以添加到pojo中的注释()并实现.@MyMessageDrivenMyCustomMessageListener

我想要的结果是“隐藏”代码(我的)的触发器,它将触发实现接口的方法(与下面我写的示例完全相同)。


答案 1

我建议阅读这篇博客文章(archive.org 上的快照),直到作者记得他可以访问Spring的组件扫描功能。

最初的问题是扫描类路径以查找具有自定义注释的类。完成此操作后,您将在独立应用程序中拥有对象,通过使用 object.getClass().getAnnotations(),您可以注入需要添加到保存自定义注释的对象中的侦听器或自定义行为。

假设您有以下自定义批注:

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMessageDriven {}

你在应用程序中用它的某个类:

@MyMessageDriven
public class MyObject {}

现在,在应用程序中的适当位置,您应该有一个方法来给出所有带有以下内容的类:MyMessageDriven

Set<Class<?>> findAllMessageDrivenClasses() {
  final StopWatch sw = new StopWatch();
  sw.start();
  final Reflections reflections = new Reflections("org.projectx", new TypeAnnotationsScanner());
  Set<Class<?>> allMessageDrivens = reflections.getTypesAnnotatedWith(MyMessageDriven.class); // NOTE HERE
  sw.stop();
  return allMessageDrivens;
}

有了这个,我假设在你的应用程序中有一个点,要么(1)你可以访问你的应用程序中的对象,要么(2)在应用程序中的所有对象上都有一个访问者或迭代器模式。因此,在某些时候,我假设我们都已将对象定位为:objects

Set<Class<?>> msgDrivenClasses = findAllMessageDrivenClasses();
for (Object o : objects) {
  if (msgDrivenClasses.contains(o.getClass()) {
    invokeTheMessageListener(o);
  }
}

另一方面,当找到具有的对象时,应该有一些可用的实现:MyMessageListenerMyMessageDriven

void invokeTheMessageListener(Object o) {
  theMessageListener.onMessage(o);
}

此答案是根据博客文章量身定制的,因此请参阅博客以了解库的配置。最后但并非最不重要的一点是,这是该问题的示例代码,可以将其重构为更模式兼容和更优雅的样式。

更新:要求目标对象应了解其自己的侦听器。因此,我建议采用以下方法。让我们有一个接口:MyMessageListenerAware

interface MyMessageListenerAware {
  MyMessageListener getMyMessageListener();
}

// and this is the original MyMessageListener
interface MyMessageListener {
  void onMessage(Object o);
}

现在,目标对象应该实现上面的接口:

class MySampleObject implements MyMessageListenerAware {

  public MyMesssageListener getMyMessageLisener() {
    return mySampleObjectImplementationOfMyMessageListener;
  }

}

有了这个,方法变得像:invokeTheMessageListener

void invokeMessageListener(Object o) {
  if (o instance MyMessageListenerAware) {
    MyMessageListener l = ((MyMessageListenerAware) o).getMyMessageListener();
    l.onMessage(o);
  }
}

虽然,我强烈建议阅读有关访客策略模式的信息。在我看来,你的目标是对应用程序中的一个公共对象/事件做出反应/行动/处理,但每个对象都有自己的解释/算法/实现。


答案 2

创建一个注释,如下所示:

 public @interface MyMessageDriven{
 }

并且您有一个可以像这样应用注释的界面:

public interface MyMessagListener {

    public void message();
}



@MyMessageDriven  
public class MyMessage implements MyMessagListener  {
   public void message(){
     System.out.println(" I am executed")
   }
} 

使用类装入器加载上述类,并使用反射检查注释是否预置。

如果存在,请使用加载的实例来执行它。

  Object obj = ClassLoader.getSystemClassLoader().loadClass("MyMessage").newInstance();
  MyMessagListener mml =  (MyMessagListener) obj;
  mml.message();

侦听器实现可以放在 MyMessage 类或实现 MessageListener 的其他类中。

在这种情况下,需要为它将要执行的操作提供实现。message()

但是这个类应该被加载,这里更重要的是你的MyMessage类是如何加载的。

这是基于MyMessage类中存在的元数据。同样,在实时场景中也是如此。

注释是类的元数据,该类表示基于提供的数据执行某些操作。如果 MyMessage 类中不存在此元数据,则无需执行方法。message()

希望这会帮助你。