Master Spring Bean Injection: XML, Annotations, FactoryBean & RegistryPostProcessor
Explore multiple Spring bean injection techniques—including XML configuration, annotation-driven @Configuration/@Bean, @Import, FactoryBean, and BeanDefinitionRegistryPostProcessor—through clear explanations, code samples, and practical examples, highlighting their advantages, drawbacks, and how to integrate them into a Spring application.
When Spring is mentioned, most people think of AOP and IOC, but the framework also provides several ways to inject beans into the container. This article examines the main Spring IOC features and presents four injection methods: XML configuration, annotation-based configuration, FactoryBean, and BeanDefinitionRegistryPostProcessor.
XML Configuration
Early Spring projects often used XML files to declare beans. The injection can be performed via setter, constructor, or field injection, supporting both value and reference types.
Example of setter injection using XML:
<code><bean name="teacher" class="org.springframework.demo.model.Teacher">
<property name="name" value="阿Q"></property>
</bean></code>Corresponding Java class:
<code>public class Teacher {
private String name;
public void setName(String name) { this.name = name; }
}</code>Drawbacks of XML configuration:
Configuration files are cumbersome to maintain alongside code, reducing development efficiency.
Large projects accumulate many XML files, making maintenance difficult.
Configuration errors are only detected at runtime, not during compilation.
Parsing XML consumes memory resources and can affect performance.
Annotation-Based Configuration
Since Spring 2.5, annotations such as @Controller, @Service, @Repository, and @Component have been widely used. Two common annotation approaches are @Configuration + @Bean and @Import.
@Configuration + @Bean
@Configuration declares a configuration class, similar to the
<beans>tag in XML, while @Bean marks a method that returns a bean instance, analogous to the
<bean>tag.
Simple example: injecting a RedisTemplate bean.
<code>@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// ... configure redisTemplate ...
return redisTemplate;
}
}</code>@Import
@Import can import third‑party configuration classes or custom selectors. It works only on classes.
Example using a custom ImportSelector:
<code>@Configuration
@Import(MyImportSelector.class)
public class MyConfig {}
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"org.springframework.demo.model.Teacher", "org.springframework.demo.model.Student"};
}
}</code>ImportBeanDefinitionRegistrar can also register beans programmatically:
<code>@Configuration
@Import(value = {MyImportBeanDefinitionRegistrar.class})
public class MyConfig {}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition tDefinition = new RootBeanDefinition(Teacher.class);
registry.registerBeanDefinition("teacher", tDefinition);
}
}</code>FactoryBean
FactoryBean is a special bean that creates other objects, similar to the factory pattern. It allows custom creation logic while still being managed by the Spring container.
<code>public class TeacherFactoryBean implements FactoryBean<Teacher> {
@Override
public Teacher getObject() throws Exception { return new Teacher(); }
@Override
public Class<?> getObjectType() { return Teacher.class; }
}</code>Register the FactoryBean using @Configuration + @Bean:
<code>@Configuration
public class MyConfig {
@Bean
public TeacherFactoryBean teacherFactoryBean() { return new TeacherFactoryBean(); }
}</code>When requesting a
Teacherbean, Spring will invoke the FactoryBean to obtain the actual instance.
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor and allows registration of additional bean definitions before the container refreshes.
<code>public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}</code>Spring internally invokes these post‑processors during startup:
<code>while (reiterate) {
// ...
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// ...
}</code>Custom implementation example:
<code>public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition bd = new RootBeanDefinition(Teacher.class);
registry.registerBeanDefinition("teacher", bd);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}</code>Bootstrapping the custom post‑processor:
<code>public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
MyBeanDefinitionRegistryPostProcessor postProcessor = new MyBeanDefinitionRegistryPostProcessor();
context.addBeanFactoryPostProcessor(postProcessor);
context.refresh();
Teacher bean = context.getBean(Teacher.class);
System.out.println(bean);
}</code>The output shows that the
Teacherbean has been successfully registered and retrieved from the Spring container.
In short, Spring now creates and controls objects for you, shifting the responsibility of object creation from the developer to the framework.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.