Skip to content

Instantly share code, notes, and snippets.

@th-schwarz
Created July 14, 2024 10:18
Show Gist options
  • Save th-schwarz/0ddce97999afd4ee8f7303d248bb9533 to your computer and use it in GitHub Desktop.
Save th-schwarz/0ddce97999afd4ee8f7303d248bb9533 to your computer and use it in GitHub Desktop.
Collect spring-managed beans before the ApplicationStarted event is started. Can be used to process things before the application starts.
/**
* SpringBeanCollector is an abstract class that implements the BeanPostProcessor interface. It provides
* functionality for collecting and processing desired Spring managed beans.
*
* <p>During the bean post-processing, SpringBeanCollector checks if the bean matches the desired types.
* Once all the desired beans are initialized, it triggers the processing logic by calling the
* process() method. The processBean() method is called internally to check and initialize the
* beans.
*/
@Slf4j
public abstract class SpringBeanCollector implements BeanPostProcessor {
private final Collection<Class<?>> wanted = new HashSet<>();
private final Collection<Object> initialized = new HashSet<>();
private boolean processed;
public BeanCollector() {
Collections.addAll(wanted, getWanted());
}
/**
* Retrieves the array of spring-managed bean classes that should be fetched by the
* post-processor.
*
* @return The array of classes.
*/
public abstract Class<?>[] getWanted();
/**
* Starts the process with the desired spring managed beans.
*
* @param wantedBeans The collection of Spring bean instances to be processed.
* @throws Exception if an error occurs during the processing.
*/
public abstract void process(Collection<Object> wantedBeans) throws Exception;
@Nullable
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
/**
* Performs post-processing after the initialization of a Spring bean. This method checks if the
* bean matches the desired types. Once all the desired beans are initialized, it triggers the
* processing logic. This method should be implemented by a subclass of PostProcessor.
*
* @param bean The Spring bean instance to be post-processed.
* @param beanName The name of the Spring bean.
* @return The post-processed bean.
* @throws BeansException if an error occurs during the post-processing.
*/
@Nullable
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
collectBean(bean);
if (!processed && wanted.isEmpty()) {
log.info("*** Wanted beans found, start #process!");
try {
process(initialized);
} catch (Exception e) {
throw new BeanInitializationException(
"Error while processing " + this.getClass().getName(), e);
}
processed = true;
}
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
private void collectBean(Object bean) {
Collection<Class<?>> toBeRemoved = new HashSet<>();
for (Class<?> wantedBean : wanted) {
if (wantedBean.isInstance(bean) && !initialized.contains(bean)) {
initialized.add(bean);
toBeRemoved.add(wantedBean);
}
}
wanted.removeAll(toBeRemoved);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment