How to implement Decorator pattern in Spring Boot
Use a BeanPostProcessor
. In this example I used P6DataSource
as a decorator that wraps an existing DataSource
. Using this approach, your existing code doesn't change since the interface is kept intact and @Autowire
of the wrapped class works as expected.
import com.p6spy.engine.spy.P6DataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import javax.sql.DataSource;
import static org.springframework.core.Ordered.LOWEST_PRECEDENCE;
@Configuration
@Order(LOWEST_PRECEDENCE)
@Slf4j
public class DataSourceBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof DataSource
&& !ScopedProxyUtils.isScopedTarget(beanName)) {
log.debug("Decorating {} with P6Spy", bean);
return new P6DataSource((DataSource) bean);
} else {
return bean;
}
}
}
I haven't really understood what is your actual problem here, but I'll try anyway.
Say you have these classes
UpperCasePrinterDecorator
LowerCasePrinterDecorator
AddAsterisksPrinterDecorator
Each of these require an instance of a Printer
, which, let's say is provided as a Spring @Component
. To use each decorator as Spring Bean you need to register it.
@Bean
@Qualifier("upperCase")
PrinterDecorator upperCasePrinterDecorator(final Printer printer) { // Injected automatically
return new UpperCasePrinterDecorator(printer);
}
@Bean
@Qualifier("lowerCase")
PrinterDecorator lowerCasePrinterDecorator(final Printer printer) {
return new LoweCasePrinterDecorator(printer);
}
@Bean
@Qualifier("asterisk")
PrinterDecorator addAsterisksPrinterDecorator(final Printer printer) {
return new AddAsterisksPrinterDecorator(printer);
}
You can then use the @Qualifier
annotation to get the right one @Autowired
@Autowired
@Qualifier("lowerCase")
private PrinterDecorator printer;