How to Build Custom @Enable Annotations in Spring Boot

This guide explains the purpose of Spring Boot's @Enable* annotations, how they rely on @Import, and walks through creating a custom @EnablePack annotation with accompanying configuration and usage in a Spring Boot application.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Build Custom @Enable Annotations in Spring Boot

@Enable* annotations in Spring Boot are used to activate specific features, such as @EnableAutoConfiguration for automatic configuration, @EnableAsync for asynchronous methods, and @EnableConfigurationProperties for binding configuration properties to beans.

Most @Enable* annotations share a common implementation detail: they use the @Import annotation to import one or more component or configuration classes.

The @Import annotation indicates one or more component classes—typically @Configuration classes—to be imported into the Spring context. Since Spring 4.2, @Import also supports importing plain classes without @Configuration.

Below is an example of creating a custom @Enable annotation called EnablePack that imports a Pack class and defines an attribute maxConnections with a default value of 1000.

@Retention(RetentionPolicy.RUNTIME)
@Import(Pack.class)
public @interface EnablePack {
    int maxConnections() default 1000;
}

The Pack class implements ImportAware and ApplicationContextAware to gain access to annotation attributes and the application context.

public class Pack implements ImportAware, ApplicationContextAware {
    private ApplicationContext ctx;
    private int maxConnections;

    @Override
    public void setImportMetadata(AnnotationMetadata annotationMetadata) {
        Map<String, Object> attributesMap = annotationMetadata.getAnnotationAttributes(EnablePack.class.getName());
        AnnotationAttributes attrs = AnnotationAttributes.fromMap(attributesMap);
        this.maxConnections = attrs.getNumber("maxConnections");
        System.out.println(ctx.getBean(ProductService.class));
        System.out.println(this.maxConnections);
    }

    public void store() {
        System.out.println(this.maxConnections);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }
}

The ImportAware interface is typically used together with @Import to activate custom functionality. Alternatively, one can extend AdviceModeImportSelector or implement ImportSelector directly.

Finally, the custom annotation is used in the Spring Boot application's main class:

@SpringBootApplication
@EnableCaching
@EnablePack(maxConnections = 10000)
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

When the application starts, the console displays the output from the Pack class, confirming that the custom @EnablePack annotation has been processed.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javabackend-developmentSpring BootCustom AnnotationImportenable
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.