【问题标题】:Custom Annotation like Lombok像 Lombok 这样的自定义注释
【发布时间】:2020-10-17 08:39:09
【问题描述】:

我想实现一个自定义注释,当其他类使用它时会向它们公开两种方法。如下图所示:

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface BaseEntity{
     public String toString(){ return "Hello" ;}
     public String toCustomString() { return "my hello";}
}

现在我想要的是任何类使用上述注释。默认情况下,它会将这些方法暴露给它,就像我们使用 @Getter 时 Lombok 所做的一样

@BaseEntity
public class Person{}
Person p = new Person();
p.toCustomString(); // this should work

【问题讨论】:

  • 嗨,有趣,也许使用Byte Buddycustom lombok annotation
  • 您始终可以创建自己的 Lombok 注释处理程序,但请记住,它有点脆弱,编写自己的代码可能不会那么痛苦
  • 是的,创建自己的 Lombok 注释处理程序对我来说也很脆弱。所以想知道是否有其他方法可以实现这一目标。

标签: java annotations lombok


【解决方案1】:

虽然不完全符合您的要求,但我认为您可以通过利用注释的类层次结构来实现您想要的:

@Retention(RetentionPolicy.RUNTIME)                                             
@Target(ElementType.TYPE)                                                       
public @interface BaseEntity {                                                  
    String string();                                                            
    String customString();                                                      
}                                                                               
                                                                                
public abstract class AbstractClass {                                           
    @Override                                                                   
    public String toString() {                                                  
        return getClass().getAnnotation(BaseEntity.class).string();             
    }                                                                           
                                                                                
    public String toCustomString() {                                            
        return getClass().getAnnotation(BaseEntity.class).customString();       
    }                                                                           
}

然后是一个具体的子类:

@BaseEntity(string = "Hello", customString = "my hello")                        
public class Example extends AbstractClass {                                    
    public static void main(String[] args) throws Exception {                   
        Example example = new Example();                                        
                                                                                
        System.out.println(example.toString());                                 
        System.out.println(example.toCustomString());                           
    }                                                                           
}

产量:

Hello                                                                           
my hello

针对您的评论,我的实际解决方案是使用默认方法定义注释和接口(这使得 toString() 实现有问题):

@BaseEntity(customString = "my hello")                                          
public class Example implements BaseEntityAnnotated {                           
    public static void main(String[] args) throws Exception {                   
        Example example = new Example();                                        
                                                                                
        System.out.println(example.toCustomString());                           
    }                                                                           
}                                                                               
                                                                                
@Retention(RetentionPolicy.RUNTIME)                                             
@Target(ElementType.TYPE)                                                       
public @interface BaseEntity {                                                  
    String customString();                                                      
}                                                                               
                                                                                
public interface BaseEntityAnnotated {                                          
    default String toCustomString() {                                           
        return this.getClass().getAnnotation(BaseEntity.class).customString();  
    }                                                                           
}

然后我实现了一个Processor,它强制使用BaseEntity 注释的实体也必须实现BaseEntityAnnotated

我在AntTaskAnnotatedAntTask.getAntTaskName()AntTaskProcessor 有示例。

【讨论】:

  • 但我想避免为此扩展类,因为 Java 只允许扩展一个类。否则,我可以直接扩展 BaseEntity。
  • 我还是直接实现接口,根本不使用注解。
  • 好的。我不知道如何提供帮助,只是说我同意 cmets 的观点,即编写类似于 Lombok 处理程序的东西来生成代码可能会很脆弱和痛苦
【解决方案2】:

您需要创建一个注解处理类(必须是javax.annotation.processing.AbstractProcessor的子类)才能真正将代码添加到Person类中。

见:http://hannesdorfmann.com/annotation-processing/annotationprocessing101

【讨论】:

  • 我检查了这个链接上的代码,但我想做的是将另一个类的方法定义添加到 Person 类。不知道我们如何实现它
  • Lombok 使用内部 javac api。
  • 是的。那么关于如何实现相同的任何建议?也许有一个带有默认实现的接口?
猜你喜欢
  • 2017-05-05
  • 2016-06-03
  • 1970-01-01
  • 2016-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多