Spring Framework offers several
methods to create and manage beans. Each method is designed for specific use
cases and advantages, making Spring flexible and adaptable to different
scenarios.
1.
Using @Component and Stereotype Annotations
Why
Use It
- Simplifies bean declaration by annotating the class
directly.
- Enables Spring to auto-scan and register beans,
reducing boilerplate code.
Implementation
//ComponentBean.java
package
com.example.springbeans.model;
import
org.springframework.stereotype.Component;
@Component
public
class ComponentBean {
public String getMessage() {
return "Hello from @Component
Bean!";
}
}
- Reason:
Ideal for lightweight classes in service, DAO, or controller layers.
2.
Using @Bean in Configuration Class
Why
Use It
- Gives explicit control over bean creation.
- Allows detailed bean configuration (e.g., constructor
arguments, custom methods).
Implementation
- AppConfig.java
package com.example.springbeans.config;
import
com.example.springbeans.model.BeanAnnotationBean;
import
org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public BeanAnnotationBean beanAnnotationBean() {
return new BeanAnnotationBean();
}
}
- Reason:
Preferred for fine-grained control and scenarios where you need to
customize bean initialization.
3.
Using XML Configuration
Why
Use It
- Used in legacy projects or when external configuration
files are needed.
- Useful for modularized configurations in non-code
setups.
If we want to explicitly use ApplicationContext
to manage both your Spring Boot
configuration and the XML-based configuration in the same context, we can
integrate them seamlessly applicationContext.xml
Using ApplicationContext
in BeanController
The ApplicationContext
will load both the Spring Boot beans and the XML-based beans. Here's how to
implement it:
1. Place applicationContext.xml
in src/main/resources
Ensure your applicationContext.xml
file is located in the src/main/resources
directory so that Spring can find it.
applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="xmlBean" class="com.example.springbeans.model.XmlBean" />
</beans>
Modify SpringBeansApplication.java
Ensure that applicationContext.xml
is loaded into the ApplicationContext
using Spring Boot's @ImportResource
annotation.
package com.example.springbeans;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("classpath:applicationContext.xml") // Import XML configuration
public class SpringBeansApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBeansApplication.class, args);
}
}
BeanController
(Main file)
In the controller, use the ApplicationContext
provided by Spring to access all beans, including those defined in applicationContext.xml
.
package com.example.springbeans.controller;
import com.example.springbeans.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BeanController {
@Autowired
private ApplicationContext context; // Autowire ApplicationContext
@Autowired
private ComponentBean componentBean;
@Autowired
private BeanAnnotationBean beanAnnotationBean;
@Autowired
private LazyBean lazyBean;
@Autowired
private PrototypeBean prototypeBean;
@GetMapping("/test")
public String testBeans() {
// Retrieve XML bean
XmlBean xmlBean = (XmlBean) context.getBean("xmlBean");
// Force lazy bean initialization
String lazyBeanMessage = lazyBean.getMessage();
// Retrieve another instance of the PrototypeBean
PrototypeBean newPrototypeBean = context.getBean(PrototypeBean.class);
return String.join("\n",
componentBean.getMessage(),
beanAnnotationBean.getMessage(),
xmlBean.getMessage(),
lazyBeanMessage,
prototypeBean.getMessage(),
newPrototypeBean.getMessage()
);
}
}
4.
Using Factory Methods
Why
Use It
- Creates complex beans where the creation logic cannot
be easily handled by the constructor or setter.
Implementation
- Factory Method Example:
package
com.example.springbeans.model;
public
class FactoryMethodBean {
private FactoryMethodBean() {}
public static FactoryMethodBean
createInstance() {
return new FactoryMethodBean();
}
public String getMessage() {
return "Hello from Factory Method
Bean!";
}
}
Reason: Essential for reusable, shared logic that creates multiple
bean instances like creating database connections or proxies.
5.
Programmatic Bean Registration
Why
Use It
- Dynamically register beans based on runtime conditions.
Implementation
- Dynamic Bean Example in Main Class:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.registerBean("dynamicBean", XmlBean.class, XmlBean::new);
- Reason:
Useful for cases like dynamically loading plugins or runtime-specific
configurations.
6.
Using Lazy Initialization
Why
Use It
- Avoids initializing beans that are not immediately
required.
- Improves startup performance.
Implementation
- Lazy Bean Example:
@Component
@Lazy
public class LazyBean {
public LazyBean() {
System.out.println("Lazy
Bean Created!");
}
}
- Reason:
Reduces resource consumption for beans used in rare scenarios.
7.
Using Scoped Beans
Why
Use It
- Controls the lifecycle of beans based on their scope (singleton, prototype, request, etc.).
Implementation
- Prototype Bean Example:
@Component
@Scope("prototype")
public class PrototypeBean {
public PrototypeBean() {
System.out.println("Prototype
Bean Created!");
}
}
- Reason:
Important for managing beans with specific lifecycles, like
session-specific data.
8.
Using Conditional Beans
Why
Use It
- Dynamically create beans based on conditions like
properties or environment variables.
Implementation
- Conditional Bean Example:
package
com.example.springbeans.model;
public
class ConditionalBean {
public String getMessage() {
return "Hello from Conditional
Bean!";
}
}
Reason: Makes the application more flexible and configurable
without changing the code.
import
com.example.springbeans.model.ConditionalBean;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import
org.springframework.context.annotation.Bean;
@Bean
@ConditionalOnProperty(name
= "feature.enabled", havingValue = "true", matchIfMissing =
false)
public
ConditionalBean conditionalBean() {
return new ConditionalBean();
}
Project
to Demonstrate All Methods
Directory
Structure
src/main/java/com/example/springbeans/
- SpringBeansApplication.java
- config/
- AppConfig.java
- model/
- ComponentBean.java
- BeanAnnotationBean.java
- XmlBean.java
- FactoryMethodBean.java
- LazyBean.java
- PrototypeBean.java
When to Use Each Method
Method |
Use
Case |
@Component |
Lightweight, auto-detected
components. |
@Bean |
Explicit, programmatic bean
definitions. |
XML Configuration |
Legacy or modularized, external
configurations. |
Factory Methods |
Complex creation logic or shared
factory logic. |
Lazy Initialization |
Beans that are rarely used. |
Scoped Beans |
Beans with specific lifecycles
like per-request or session. |
Conditional Beans |
Environment or property-driven
configurations. |
FactoryBean |
Special objects like proxies or
external libraries requiring custom logic. |
Why
Use This ApplicationContext Approach?
- Unified Context:
- By integrating applicationContext.xml into the Spring Boot context, you avoid creating
separate contexts.
- This simplifies configuration and avoids potential
issues with duplicate or conflicting beans.
- Flexibility:
- You can seamlessly use both XML-based and
annotation-based configurations.
- Reusability:
- The ApplicationContext is shared across the application, improving
performance and consistency.
This implementation ensures that all
beans, whether defined via XML or annotations, are accessible in a single ApplicationContext.