Skip to content

Commit

Permalink
Make bean customizer static to appease AOT (#671)
Browse files Browse the repository at this point in the history
  • Loading branch information
onobc authored May 5, 2024
1 parent 5c7655d commit e7f31ae
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 84 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,53 +21,47 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.log.LogAccessor;
import org.springframework.pulsar.config.ConcurrentPulsarListenerContainerFactory;
import org.springframework.pulsar.config.ConcurrentPulsarListenerContainerFactoryCustomizer;
import org.springframework.util.CollectionUtils;

/**
* A {@link BeanPostProcessor} that applies a customizer to beans of a specified type.
* Applies a {@link ConcurrentPulsarListenerContainerFactoryCustomizer} to all
* {@link ConcurrentPulsarListenerContainerFactory} beans.
* <p>
* There must be only one customizer in the application context in order for it to be
* applied.
*
* @param <B> the type of bean to customize
* @param <C> the type of customizer
* @author Chris Bono
*/
class BeanCustomizerPostProcessor<B, C extends BeanCustomizer<B>>
class ConcurrentPulsarListenerContainerFactoryBeanCustomizerPostProcessor
implements BeanPostProcessor, ApplicationContextAware {

private final LogAccessor logger = new LogAccessor(getClass());

private final Class<B> beanType;

private final Class<C> customizerType;

private ApplicationContext applicationContext;

BeanCustomizerPostProcessor(Class<B> beanType, Class<C> customizerType) {
this.beanType = beanType;
this.customizerType = customizerType;
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

@SuppressWarnings("unchecked")
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (this.beanType.isInstance(bean)) {
B typedBean = this.beanType.cast(bean);
var customizers = this.applicationContext.getBeansOfType(this.customizerType);
if (bean instanceof ConcurrentPulsarListenerContainerFactory<?> containerFactory) {
var customizers = this.applicationContext
.getBeansOfType(ConcurrentPulsarListenerContainerFactoryCustomizer.class);
if (CollectionUtils.isEmpty(customizers)) {
return bean;
}
if (customizers.size() > 1) {
this.logger.warn("Found multiple %s beans [%s] - must be only 1 in order to apply"
.formatted(this.customizerType.getSimpleName(), customizers.keySet()));
this.logger.warn("Found multiple %s beans [%s] - must be only 1 in order to apply".formatted(
ConcurrentPulsarListenerContainerFactoryCustomizer.class.getSimpleName(),
customizers.keySet()));
}
else {
customizers.values().stream().forEach((c) -> c.customize(typedBean));
customizers.values().forEach((c) -> c.customize(containerFactory));
}
}
return bean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,13 @@

package org.springframework.pulsar.annotation;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.ResolvableType;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.pulsar.config.ConcurrentPulsarListenerContainerFactory;
import org.springframework.pulsar.config.ConcurrentPulsarListenerContainerFactoryCustomizer;
import org.springframework.pulsar.config.PulsarAnnotationSupportBeanNames;
import org.springframework.pulsar.config.PulsarListenerEndpointRegistry;
import org.springframework.pulsar.config.PulsarReaderEndpointRegistry;
import org.springframework.pulsar.core.PulsarTemplate;
import org.springframework.pulsar.core.PulsarTemplateCustomizer;

/**
* An {@link ImportBeanDefinitionRegistrar} class that registers a
Expand All @@ -51,27 +45,13 @@ public class PulsarBootstrapConfiguration implements ImportBeanDefinitionRegistr
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition("pulsarTemplateCustomizerPostProcessor")) {
var postProcessorType = ResolvableType.forClassWithGenerics(BeanCustomizerPostProcessor.class,
PulsarTemplate.class, PulsarTemplateCustomizer.class);
@SuppressWarnings("unchecked")
var beanDef = BeanDefinitionBuilder
.rootBeanDefinition(postProcessorType,
() -> new BeanCustomizerPostProcessor<>(PulsarTemplate.class, PulsarTemplateCustomizer.class))
.getBeanDefinition();
registry.registerBeanDefinition("pulsarTemplateCustomizerPostProcessor", beanDef);
registry.registerBeanDefinition("pulsarTemplateCustomizerPostProcessor",
new RootBeanDefinition(PulsarTemplateBeanCustomizerPostProcessor.class));
}

if (!registry.containsBeanDefinition("concurrentContainerFactoryCustomizerPostProcessor")) {
var postProcessorType = ResolvableType.forClassWithGenerics(BeanCustomizerPostProcessor.class,
ConcurrentPulsarListenerContainerFactory.class,
ConcurrentPulsarListenerContainerFactoryCustomizer.class);
@SuppressWarnings("unchecked")
var beanDef = BeanDefinitionBuilder
.rootBeanDefinition(postProcessorType,
() -> new BeanCustomizerPostProcessor<>(ConcurrentPulsarListenerContainerFactory.class,
ConcurrentPulsarListenerContainerFactoryCustomizer.class))
.getBeanDefinition();
registry.registerBeanDefinition("concurrentContainerFactoryCustomizerPostProcessor", beanDef);
registry.registerBeanDefinition("concurrentContainerFactoryCustomizerPostProcessor",
new RootBeanDefinition(ConcurrentPulsarListenerContainerFactoryBeanCustomizerPostProcessor.class));
}

if (!registry
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.pulsar.annotation;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.log.LogAccessor;
import org.springframework.pulsar.core.PulsarTemplate;
import org.springframework.pulsar.core.PulsarTemplateCustomizer;
import org.springframework.util.CollectionUtils;

/**
* Applies a {@link PulsarTemplateCustomizer} to all {@link PulsarTemplate} beans.
* <p>
* There must be only one customizer in the application context in order for it to be
* applied.
*
* @author Chris Bono
*/
class PulsarTemplateBeanCustomizerPostProcessor implements BeanPostProcessor, ApplicationContextAware {

private final LogAccessor logger = new LogAccessor(getClass());

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

@SuppressWarnings("unchecked")
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof PulsarTemplate<?> template) {
var customizers = this.applicationContext.getBeansOfType(PulsarTemplateCustomizer.class);
if (CollectionUtils.isEmpty(customizers)) {
return bean;
}
if (customizers.size() > 1) {
this.logger.warn("Found multiple %s beans [%s] - must be only 1 in order to apply"
.formatted(PulsarTemplateCustomizer.class.getSimpleName(), customizers.keySet()));
}
else {
customizers.values().stream().forEach((c) -> c.customize(template));
}
}
return bean;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@

package org.springframework.pulsar.config;

import org.springframework.pulsar.annotation.BeanCustomizer;

/**
* Callback interface that can be implemented to customize a
* {@link ConcurrentPulsarListenerContainerFactory}.
*
* @param <T> The message payload type
* @author Chris Bono
*/
public interface ConcurrentPulsarListenerContainerFactoryCustomizer<T>
extends BeanCustomizer<ConcurrentPulsarListenerContainerFactory<T>> {
@FunctionalInterface
public interface ConcurrentPulsarListenerContainerFactoryCustomizer<T> {

/**
* Customize a {@link ConcurrentPulsarListenerContainerFactory}.
* @param containerFactory the factory to customize
*/
void customize(ConcurrentPulsarListenerContainerFactory<T> containerFactory);

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@

package org.springframework.pulsar.core;

import org.springframework.pulsar.annotation.BeanCustomizer;

/**
* Callback interface that can be implemented to customize a {@link PulsarTemplate}.
*
* @param <T> the payload type of the template
* @author Chris Bono
*/
public interface PulsarTemplateCustomizer<T> extends BeanCustomizer<PulsarTemplate<T>> {
@FunctionalInterface
public interface PulsarTemplateCustomizer<T> {

/**
* Customize a {@link PulsarTemplate}.
* @param template the template to customize
*/
void customize(PulsarTemplate<T> template);

}

0 comments on commit e7f31ae

Please sign in to comment.