Spring Boot 3 Essentials: Lifecycle, Bean Creation, Validation & More
This article presents a comprehensive collection of over 50 Spring Boot 3 practical examples, covering core topics such as the Lifecycle and SmartLifecycle interfaces, custom FactoryBean implementations, graceful shutdown in non‑web environments, resource injection, parameter validation, and type conversion techniques.
Spring Boot 3 Practical Cases Collection – more than 50 curated articles that demonstrate advanced usage of Spring Boot features.
1. Lifecycle Interface
The Lifecycle interface defines start/stop lifecycle control methods. It allows beans or the container (usually the ApplicationContext) to implement start and stop operations.
public interface Lifecycle {
// executed before the Spring container starts
void start();
// executed when the Spring container is shutting down
void stop();
// indicates whether the component is currently running
boolean isRunning();
}Note: The standard org.springframework.context.Lifecycle is a simple contract for explicit start/stop notifications and does not trigger automatic start on context refresh. For finer control, implement org.springframework.context.SmartLifecycle .
Example implementation:
public class PackLifecycle implements SmartLifecycle {
private volatile boolean running;
@Override
public void start() {
this.running = true;
System.out.println("lifecycle start ... ");
}
@Override
public void stop() {
this.running = false;
System.out.println("lifecycle stop ... ");
}
@Override
public boolean isRunning() {
return running;
}
}2. FactoryBean Interface
Implement FactoryBean when you need full control over bean instantiation. T getObject(): returns the created object instance (may be shared). boolean isSingleton(): true if the factory returns a singleton. Class<?> getObjectType(): returns the type of object produced.
Example:
public class User {}
@Component("user")
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}Injecting the produced User bean:
@Resource
private User user;Accessing the factory itself (note the leading & in the bean name):
try (GenericApplicationContext context = new GenericApplicationContext()) {
System.out.println(context.getBean("&user"));
}3. Graceful Shutdown in Non‑Web Environments
Register a JVM shutdown hook to ensure proper bean destruction:
public class User implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("User Object destroy...");
}
}
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(User.class);
// Starts a thread that invokes onClose, allowing lifecycle methods to run
context.registerShutdownHook();
context.refresh();
}
// Console output (if registerShutdownHook is called):
// User Object destroy...In Spring Boot, registerShutdownHook() is invoked automatically.
4. Resource Injection
Inject resources directly with @Value:
@Value("${pack.images:file:///d:/images/1.png}")
private Resource res;
@GetMapping("/res0")
public void res0(HttpServletResponse response) throws Exception {
response.setContentType("image/png");
StreamUtils.copy(res.getInputStream(), response.getOutputStream());
}Inject an array of resources:
@Component
public class PackResource {
private final Resource[] templates;
public PackResource(@Value("${pack.templates.path}") Resource[] templates) {
this.templates = templates;
}
}Configuration example:
pack:
templates:
path: classpath*:com/pack/templates/*.ftlImplement ResourceLoaderAware when you only need the ResourceLoader interface:
@Component
public class PackResourceLoader implements ResourceLoaderAware {
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
Resource resource = resourceLoader.getResource("classpath:com/pack/templates/1.txt");
System.out.println(StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8));
}
}5. Parameter Validation
Typical usage in a controller method:
@PostMapping("")
public Object save(@Validated @RequestBody User user, BindingResult errors) {
// TODO
}In any managed bean, inject Validator and invoke it manually:
private final Validator validator;
public UserService(Validator validator) {
this.validator = validator;
}
public void save(User user) {
Errors errors = new BeanPropertyBindingResult(user, "user");
validator.validate(user, errors);
if (errors.hasErrors()) {
// handle errors
}
}When not using Spring Boot, register a LocalValidatorFactoryBean manually:
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}6. Type Conversion
Use ConversionService for explicit type conversion, which is auto‑configured in Spring Boot and can be injected into any bean.
private final ConversionService conversionService;
public PackComponent(ConversionService conversionService) {
this.conversionService = conversionService;
}
public Object convert(Object source, Class<?> targetType) {
if (source == null || targetType == null) {
throw new IllegalArgumentException("Source or target type cannot be null");
}
return conversionService.convert(source, targetType);
}These six sections provide a solid foundation for mastering Spring Boot 3 advanced features.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
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.
