如何使用后面的代码创建自定义注释

ray*_*man 37 java annotations dependency-injection interface

我想创建自己的自定义注释.我的框架是Stand alone java应用程序.当有人注释他的pojo类时,后面的"隐藏"代码将触发方法.

例如,今天在Java EE中我们有@MessageDriven注释.当您使用@MessageDrivenMessageListener接口并使用MessageListener接口注释您的类时,会触发一个后面的代码onMessage(Message msg).当消息从队列/主题到达时.

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

我想要的结果是触发"隐藏"代码(我的),它将触发一个实现接口的方法(就像我在下面写的样本一样).

nob*_*beh 35

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

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

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

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMessageDriven {}
Run Code Online (Sandbox Code Playgroud)

你在你的应用程序中使用它一些类:

@MyMessageDriven
public class MyObject {}
Run Code Online (Sandbox Code Playgroud)

现在,在应用程序的适当位置,您应该有一个方法来提供所有携带的类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;
}
Run Code Online (Sandbox Code Playgroud)

有了这个,我假设您的应用程序中有一点要么(1)您可以访问应用程序中的对象,或者(2)应用程序中的所有对象都有访问者或迭代器模式.因此,在某些方面,我假设我们将所有目标对象都包括在内objects:

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

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

void invokeTheMessageListener(Object o) {
  theMessageListener.onMessage(o);
}
Run Code Online (Sandbox Code Playgroud)

此答案是根据博客条目量身定制的,因此请参阅博客以了解库的配置.而且,最后但并非最不重要的是,这是问题的示例代码,它可以重构为更多模式兼容和优雅的风格.

更新:要求目标对象应该知道自己的侦听器.所以,我建议采用以下方法.我们有一个界面MyMessageListenerAware:

interface MyMessageListenerAware {
  MyMessageListener getMyMessageListener();
}

// and this is the original MyMessageListener
interface MyMessageListener {
  void onMessage(Object o);
}
Run Code Online (Sandbox Code Playgroud)

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

class MySampleObject implements MyMessageListenerAware {

  public MyMesssageListener getMyMessageLisener() {
    return mySampleObjectImplementationOfMyMessageListener;
  }

}
Run Code Online (Sandbox Code Playgroud)

有了这个,方法invokeTheMessageListener就像:

void invokeMessageListener(Object o) {
  if (o instance MyMessageListenerAware) {
    MyMessageListener l = ((MyMessageListenerAware) o).getMyMessageListener();
    l.onMessage(o);
  }
}
Run Code Online (Sandbox Code Playgroud)

虽然,我强烈建议阅读有关访客策略模式.在我看来,你需要做的事情就像你需要某些对象对应用程序中的公共对象/事件做出反应/行动/处理,但每个对象都有自己的解释/算法/实现.


UVM*_*UVM 10

创建一个这样的注释:

 public @interface MyMessageDriven{
 }
Run Code Online (Sandbox Code Playgroud)

你有一个可以应用这样的注释的接口:

public interface MyMessagListener {

    public void message();
}



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

使用类加载器加载上面的类并使用反射检查注释是否有效.

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

  Object obj = ClassLoader.getSystemClassLoader().loadClass("MyMessage").newInstance();
  MyMessagListener mml =  (MyMessagListener) obj;
  mml.message();
Run Code Online (Sandbox Code Playgroud)

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

在这种情况下,需要提供实现message()目标.

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

这是基于MyMessage类中存在的元数据.类似的方式,在实时场景中,这也是它的工作原理.

注释是一个类的元数据,它根据提供的数据说,做一些事情.如果MyMessage类中没有这个元数据,则不需要执行message()方法.

希望这会帮助你.