1

I have some repeated annotations in multiple classes. It looks like this -

@Configuration
@Data
@Slf4j
@ConfigurationProperties(prefix = "hello")
@PropertySource(value = "classpath:hello.yml", factory = YamlSourceFactory.class)`

I would like to combine and make a single Annotation class out of it. I want to write something like this -

@Configuration
@Data
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@PropertySource(value = this.value, factory = this.factory)
@ConfigurationProperties(prefix = this.key)
public @interface CustomAnnotation {
    String name() default "";
    String[] key();
    String[] value();
    Class<? extends PropertySourceFactory> factory() default YamlSourceFactory.class;
}

so that in all my other files I can write only one line and it is taken care of by my Custom Annotation - @CustomAnnotation(key = "hello", value = "classpath:hello.yml")

Is this something possible to achieve ?

MuCh
  • 103
  • 1
  • 9
  • Some of those annotations are lombok, and lombok wouldn't support this. Not that any of the others do, either. There are plans to add meta annotation systems to lombok, though they won't be able to do anything other than what the lombok annotations do, and that feature is still in the 'design' phase. – rzwitserloot Sep 08 '22 at 17:03
  • @rzwitserloot Thanks. Yes, I also realized `@Data` and `@Slf4j` won't work. `@Configuration` works though. However, I am more concerned about the `@PropertySource` and `@ConfigurationProperties` annotations as they are more annoying to type again and again. Any idea on these ? Especially getting the values out and setting it is something I am not able to do. – MuCh Sep 08 '22 at 18:26
  • Does this answer your question? [Is there something like Annotation Inheritance in java?](https://stackoverflow.com/questions/7761513/is-there-something-like-annotation-inheritance-in-java) (especially [this answer](https://stackoverflow.com/a/18585833/639520)) – E-Riz Sep 08 '22 at 20:31

1 Answers1

0

I faced similar problem and this solution works for me:

This is the case:

package com.something.something;

import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Primary
@Scope
@Component
@Lazy
public @interface CustomComponent{

        /**
         * Setting the scope of the beans
         * Means: @Scope(value = "scope")
         * @return
         */
        @AliasFor(
            annotation = Scope.class,
            attribute = "value"
        )
        String scope() default SCOPE_PROTOTYPE;

        /**
         * Setting the name of the beans.
         * I don't know why but if I renamed this, it didn't work. I could rename the others. 
         * Means: @Component(value = "name")
         * @return
         */
        @AliasFor(
            annotation = Component.class,
            attribute = "value"
        )
        String value() default "";

        /**
         * Setting the bean is lazy or not
         * Means: @Lazy(value = true)
         * @return
         */
        @AliasFor(
            annotation = Lazy.class,
            attribute = "value"
        )
        boolean isLazy() default false;


}

How to use:

@CustomComponent( scope = "SCOPE_SINGLETON", value = "bean-name", isLazy = true);

I hope you can transform it to your case.

Péter Baráth
  • 316
  • 2
  • 10