001package io.avaje.inject;
002
003import java.lang.annotation.Repeatable;
004import java.lang.annotation.Retention;
005import java.lang.annotation.Target;
006
007import static java.lang.annotation.ElementType.*;
008import static java.lang.annotation.RetentionPolicy.RUNTIME;
009import static java.lang.annotation.RetentionPolicy.SOURCE;
010
011/**
012 * Identify a bean as component with singleton scope that avaje-inject will use.
013 * <p>
014 * This is an alternative to using the standard <code>@Singleton</code> annotation.
015 * We generally use <code>@Component</code> when we:
016 * <ul>
017 *   <li>Want to use avaje-inject in a project that has some other library using <code>@Singleton</code></li>
018 *   <li>Want to support BOTH <code>javax.inject</code> and <code>jakarta.inject</code></li>
019 * </ul>
020 *
021 * <h3>Example</h3>
022 * <pre>{@code
023 *
024 * @Component
025 * class MyEmailSender implements EmailSender {
026 *
027 *   ...
028 * }
029 * }</pre>
030 *
031 * <h3>Ignoring <em>@Singleton</em></h3>
032 * <p>
033 * Set {@link InjectModule#ignoreSingleton()} <code>true</code> to get avaje-inject to ignore
034 * classes annotated with <code>@Singleton</code>. Typically, we want another DI library to use
035 * those classes and want avaje-inject to co-exist independently.
036 * <p>
037 *
038 * <pre>{@code
039 *
040 *   @InjectModule(name = "coffee", ignoreSingleton = true)
041 *   package coffee;
042 *
043 *   import io.avaje.inject.InjectModule;
044 *
045 * }</pre>
046 *
047 * @see InjectModule#ignoreSingleton()
048 */
049@Target(TYPE)
050@Retention(RUNTIME)
051public @interface Component {
052
053  /**
054   * Specify types to generate DI classes for.
055   *
056   * <p>These types are typically in an external project / dependency or otherwise types that we
057   * can't or don't want to explicitly annotate with {@code @Singleton}/{@code @Component}.
058   *
059   * <p>Typically, we put this annotation on a package/module-info.
060   *
061   * <pre>{@code
062   * Component.Import({CustomerService.class, ProductService.class, ...})
063   * package org.example.processor;
064   *
065   * }</pre>
066   */
067  @Retention(SOURCE)
068  @Target({TYPE, PACKAGE, MODULE})
069  @Repeatable(Imports.class)
070  @interface Import {
071
072    /** Types to generate DI classes for. */
073    Class<?>[] value();
074
075    /** What kind of bean */
076    Kind kind() default Kind.SINGLETON;
077
078    enum Kind { SINGLETON, PROTOTYPE, LAZY }
079  }
080
081  /**
082   * @see Import
083   */
084  @Retention(SOURCE)
085  @Target({TYPE, PACKAGE, MODULE})
086  @interface Imports {
087    Import[] value();
088  }
089}