Skip to content

Instantly share code, notes, and snippets.

@joshlong
Created May 22, 2025 14:31
Show Gist options
  • Save joshlong/779201af6211b87e26b1c2e86a52271d to your computer and use it in GitHub Desktop.
Save joshlong/779201af6211b87e26b1c2e86a52271d to your computer and use it in GitHub Desktop.
an example application that demonstrates creating a running background thread and that demonstrates selectively destroying bean definitions based on some criteria (in this case, the type of the bean)
package com.example.lifecycle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
@SpringBootApplication
public class LifecycleApplication {
public static void main(String[] args) {
SpringApplication.run(LifecycleApplication.class, args);
}
@Bean
ApplicationRunner runner() {
return new ApplicationRunner() {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("hello short live process");
}
};
}
@Bean
ApplicationRunner farmRunner(Map<String, Animal> animals) {
return args -> {
System.out.println("there are " + animals.size() + " animals.");
animals.forEach((name, animal) -> System.out.println(name + " " + animal));
};
}
@Bean
static AnimnalBeanFactoryPostProcessor animnalBeanFactoryPostProcessor() {
return new AnimnalBeanFactoryPostProcessor();
}
}
@Component
class Cat implements Animal {
Cat() {
System.out.println("meow");
}
}
@Component
class Dog implements Animal {
Dog() {
System.out.println("woof");
}
}
@Component
class OtherService {
@EventListener
void after(ApplicationReadyEvent readyEvent) {
System.out.println("after ApplicationReadyEvent");
}
OtherService() {
System.out.println("OtherService");
}
}
interface Animal {
}
class AnimnalBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (var beanName : beanFactory.getBeanDefinitionNames()) {
var beanDefinition = beanFactory.getBeanDefinition(beanName);
var type = beanFactory.getType(beanName);
if (type != null && Animal.class.isAssignableFrom(type)) {
if (beanFactory instanceof DefaultListableBeanFactory dlac) {
dlac.removeBeanDefinition(beanName);
System.out.println("deleting " + beanName + '.');
}
}
// if (type != null && Animal.class.isAssignableFrom(type)) {
// beanDefinition.setLazyInit(true);
// }
}
}
}
@Component
class StatefulService implements SmartLifecycle, Runnable {
private final AtomicBoolean running = new AtomicBoolean(false);
private final Executor executor = Executors.newSingleThreadExecutor();
@Override
public void start() {
System.out.println("start");
running.set(true);
this.executor.execute(this);
}
@Override
public void stop() {
System.out.println("stop");
running.set(false);
}
@Override
public boolean isRunning() {
return this.running.get();
}
@Override
public void run() {
while (this.running.get()) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment