Master 11 Spring Boot Bean Registration Techniques for Dynamic Applications

Explore 11 practical Spring Boot bean registration methods—from simple @Component scanning to advanced ImportSelector, FactoryBean, and runtime dynamic registration—detailing code examples, use cases, and configuration steps, enabling developers to choose the optimal approach for flexible, modular applications.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master 11 Spring Boot Bean Registration Techniques for Dynamic Applications

1. Introduction

In Spring Boot, flexible bean registration is key to building loosely coupled applications. This article systematically reviews multiple bean registration methods and typical scenarios: using @Component family annotations for zero‑configuration component scanning; @Bean for explicit control; @Import and ImportSelector for modular dynamic configuration; FactoryBean for complex object creation; auto‑configuration mechanisms for starter development; and programmatic ApplicationContext registration for runtime dynamic needs. These methods cover the full spectrum from simple business components to highly customized scenarios, helping developers choose the optimal solution.

2. Practical Cases

2.1 Using @Component

Beyond @Component, you can use strategy annotations such as @Service, @Controller, @Repository. Application scenario: regular business components like Service, Controller, Repository layers. Spring Boot scans these annotations at startup and registers the classes as beans.

@Component
public class UserComponent {
}

2.2 Using @Bean

In a @Configuration class, annotate a method with @Bean to return an object instance. The method name serves as the bean identifier (you can also specify a name). Application scenario: integrating third‑party libraries (e.g., connection pools, utilities) or beans requiring custom initialization logic.

@Configuration
public class AppConfig {
  @Bean
  UserComponent userComponent() {
    return new UserComponent();
  }
}

2.3 Using @Import

Use @Import in a configuration class to import other configuration classes or ordinary classes, making them beans.

Application scenarios:

Modular configuration: split multiple config classes and combine as needed.

Quickly register a single bean, equivalent to annotating the class with @Component.

@Configuration
@Import({UserComponent.class})
public class AppConfig {
}

2.4 Using ImportSelector

Implement the ImportSelector interface, override selectImports() to return an array of fully qualified class names to be imported.

Application scenario: dynamically import configuration classes based on conditions (properties, environment variables) for on‑demand loading.

public class PackImportSelector implements ImportSelector {
  @Override
  public String[] selectImports(AnnotationMetadata metadata) {
    return new String[] { "com.pack.registry.component.UserComponent" };
  }
}
@Configuration
@Import({PackImportSelector.class})
public class AppConfig {
}

2.5 Using ImportBeanDefinitionRegistrar

Implement ImportBeanDefinitionRegistrar, override registerBeanDefinitions() to dynamically register beans via BeanDefinitionRegistry.

Application scenario: conditionally register beans based on environment variables, classpath presence, etc., enabling flexible programmatic configuration.

public class PackImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
  private final Environment environment;
  public PackImportBeanDefinitionRegistrar(Environment environment) {
    this.environment = environment;
  }
  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    if ("true".equals(environment.getProperty("pack.app.enabled"))) {
      RootBeanDefinition beanDefinition = new RootBeanDefinition(UserComponent.class);
      registry.registerBeanDefinition("userComponent", beanDefinition);
    }
  }
}
@Configuration
@Import({PackImportBeanDefinitionRegistrar.class})
public class AppConfig {
}

2.6 Using FactoryBean

Define a factory bean that implements FactoryBean and returns an object instance.

Application scenario: control bean creation process or return complex objects such as proxies or dynamically generated beans.

@Component
public class UserFactoryBean implements FactoryBean<UserComponent> {
  @Override
  public UserComponent getObject() throws Exception {
    ProxyFactory factory = new ProxyFactory();
    factory.setTarget(new UserComponent());
    factory.addAdvice(new MethodInterceptor() {
      @Override
      public Object invoke(MethodInvocation invocation) throws Throwable {
        System.err.println("log...");
        return invocation.proceed();
      }
    });
    return (UserComponent) factory.getProxy();
  }
  @Override
  public Class<?> getObjectType() {
    return UserComponent.class;
  }
  @Override
  public boolean isSingleton() {
    return true;
  }
}

2.7 Using @ComponentScan

Add @ComponentScan on a configuration or main class to specify packages to scan at startup.

Application scenario: customize scanning paths to register classes annotated with @Component, @Service, @Repository, @Controller, etc., as beans.

@Component
@ComponentScan(basePackages = "com.xxx.")
public class ScanConfig {
}

2.8 Using BeanFactoryPostProcessor

Implement BeanDefinitionRegistryPostProcessor, use BeanDefinitionBuilder to construct bean definitions, and register them via BeanDefinitionRegistry.

Application scenario: modify or enhance bean definitions during the bean definition phase, such as changing scope or initialization methods.

@Component
public class PackBeanRegistryProcessor implements BeanDefinitionRegistryPostProcessor {
  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    AbstractBeanDefinition definition = BeanDefinitionBuilder
      .genericBeanDefinition(UserComponent.class)
      .setScope("singleton")
      .getBeanDefinition();
    registry.registerBeanDefinition("userComponent", definition);
  }
}

2.9 Using @Enable* Annotations

Create custom @Enable* annotations combined with @Import or ImportSelector to enable specific functionality and bean registration.

Application scenario: trigger related bean registration when a particular feature is enabled, useful for custom components.

public class PackImportSelector implements ImportSelector {
  @Override
  public String[] selectImports(AnnotationMetadata metadata) {
    return new String[] { "com.pack.registry.component.UserComponent" };
  }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({PackImportSelector.class})
public @interface EnableDynamicBean {
}

2.10 Runtime Dynamic Registration

Manually register beans at runtime using ApplicationContext.registerBean() or ConfigurableApplicationContext.registerSingleton().

Application scenario: create bean instances dynamically based on configuration files or user input.

@Component
public class RuntimeRegistry implements ApplicationContextAware {
  private ApplicationContext context;
  @Override
  public void setApplicationContext(ApplicationContext context) throws BeansException {
    this.context = context;
  }
  public void registry() {
    AutowireCapableBeanFactory acbf = this.context.getAutowireCapableBeanFactory();
    if (acbf instanceof SingletonBeanRegistry registry) {
      UserComponent uc = new UserComponent();
      acbf.autowireBean(uc);
      acbf.initializeBean(uc, "uc");
      registry.registerSingleton("uc", uc);
    }
  }
}

2.11 Auto‑Configuration

Configure auto‑configuration classes via spring.factories or META‑INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports, allowing common components to be automatically discovered when the dependency is added.

Application scenario: develop reusable components that are auto‑registered by the container upon startup.

For Spring Boot 2.7+ create a file under META‑INF/spring.factories with the fully qualified class name, e.g.:

com.pack.registry.component.UserComponent

For versions below 2.7, create META‑INF/spring.factories containing:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pack.registry.component.UserComponent
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 BootDependency InjectionBean Registration
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.