简体   繁体   中英

Best way to pass data from custom annotation to spring @PostConstruct?

i am writting a framework and I need to pass some information from an annotation to a PostConstruct method.

What iam currently failing at is getting the data in a nice way.

How can i get from here:

@EnableCoolFeature(data1="foo", data2="bar")
public class MainApp {
    public static void main (){ //SpringApp init etc }
}

To here:

@Configuration
public class CoolFeatureConfiguration{

    @PostConstruct
    void processData(){
        //how to get the data in here?
    }
}

Also note that the user can enable "@EnableCoolFeature" multiple times on different Configurations

EDIT: i found a way which works for me

var beanNamesForAnnotation = applicationContext.getBeansWithAnnotation(EnableCoolFeature.class);

for (var tuple : beanNamesForAnnotation.entrySet()) {
    var result = applicationContext.findAnnotationOnBean(tuple.getKey(), EnableCoolFeature.class);
    //the magic!
}

An example can be found here .

You need to implement something like this:

import java.lang.annotation.Annotation;
import org.springframework.core.annotation.AnnotationUtils;

@EnableCoolFeature(data1 = "foo", data2 = "bar")
public class MainApp {

  public static void main ()
  {
    try {
      Annotation enableCoolFeatureAnnotation = AnnotationUtils.findAnnotation(MainApp.class, EnableCoolFeature.class);
      System.out.println("@EnableCoolFeature of MainApp.class is: "+enableCoolFeatureAnnotation);

      System.out.println("@EnableCoolFeature value: "+AnnotationUtils.getValue(enableCoolFeatureAnnotation));
      System.out.println("@EnableCoolFeature default value data1: "+AnnotationUtils.getDefaultValue(enableCoolFeatureAnnotation, "data1"));
      System.out.println("@EnableCoolFeature default value data2: "+AnnotationUtils.getDefaultValue(enableCoolFeatureAnnotation, "data2"));
      System.out.println("@EnableCoolFeature data1: "+AnnotationUtils.getValue(enableCoolFeatureAnnotation, "data1"));
      System.out.println("@EnableCoolFeature data2: "+AnnotationUtils.getValue(enableCoolFeatureAnnotation, "data2"));
      
      String data1 = (String)AnnotationUtils.getValue(enableCoolFeatureAnnotation, "data1");
      String data2 = (String)AnnotationUtils.getValue(enableCoolFeatureAnnotation, "data2");
      
      // ... pass the arguments to Spring Boot: https://www.baeldung.com/spring-boot-command-line-arguments
      String[] args = { data1, data2 };
      SpringApplication.run(MainApp.class, args);
      
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Edit: As the author asked how could unknown annotations be processed dynamically, here is an example. Before the code above can be executed, we need to retrieve the annotation classes and the field names according to a defined criteria. Paste the following code right after try { in the code above:

    try {
        MergedAnnotations mas = MergedAnnotations.from(PaperlessSpringApp.class);
        for (MergedAnnotation<Annotation> ma : mas)
        {
            Class<Annotation> annotationClass = ma.getType();
            
            Field[] fields = annotationClass.getFields();
            
            for (Field field:fields)
            {
                String fieldName = field.getName();
                
                // Retrieve the values as shown below with data1 and data2 but this time using annotationClass and fieldName. 
            }
        }
    ....

In the original code example MainApp.class must be replaced by a parameter Class<?> appClass that must be supplied by your users when they call the main() method from their code. Or a better solution would be to rename the method and make it an instance method (not static), then let your users inherit from MainApp and then you can use directly getClass() to get your user's app class:

// This is part of your framework:
public class MainApp {

  protected void runSpring() {
     // ... same code
  }
}

// This is the code your users would have to write:
@EnableCoolFeature(data1 = "foo", data2 = "bar")
public class YourUsersApp extends MainApp {
    
  public static void main ()
  {
    new YourUsersApp().runSpring();
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM