Please notice: The intention of my blog is to share and discuss ideas. If you use any of this in your applications you're acting at your own risk.
JSR-299 decorator pattern implementation
The decorator module provides the following features:
- Use JSR-299
@Delegatein Spring managed beans
- Support chains of multiple decorators for the same target delegate bean
- Allow to qualify decorators to decorate multiple implementations of the same interface with different decorators
- Support scoped beans, allow scoped decorators
- Integrate with Spring AOP, both dynamic JDK proxies and CGLIB proxies
- Allow definition of custom decorator and delegate annotations
The Spring-CDI decorator module is an usual Spring IoC-container extension delivered as JAR archive. You can download the module JAR and put that on the classpath of your Spring application.
Compiled Spring-CDI decorator module JAR: Version v0.9.10
Sources: Version v0.9.10
API-Doc: Version v0.9.10
Everything is hosted on a git repository on Github.com.
If the Spring-CDI decorator module JAR and its dependencies are on your classpath, all you need to do is:
DecoratorAwareBeanFactoryPostProcessorin your application context
(2) define an
javax.decorator.Decoratoras component annotation in your
The following code snippets show how you can use the decorator pattern ones you have configured your Spring application as described above. For more complex scenarios see my unit test cases.
Let's assume you have a business interface called:
This is your implementation of the service.
You want to do some transaction and security stuff, but you do not want to mess up the business code with it.
For security you'd write a decorator that points to the
To seperate the cross-cutting-concerns you write another decorator for transaction handling that points to the
Then you can just use standard Spring
@Autowiredannotation to make that work. The injected bean will be decorated with your new security and transaction decorator.
How it works
The core is the
DecoratorAwareBeanFactoryPostProcessorthat scans the registered bean definitions for existing decorators. It gathers meta data and stores that data in the
DecoratorAwareBeanPostProcessoruses the meta data to wire the decorators into a chain and creates a CGLIB proxy that intercepts method calls to the target delegate bean. It redirects those calls to the decorator chain. The
DecoratorAutowireCandidateResolverapplies autowiring rules specific to the CDI decorator pattern. It also uses meta data to do that.
The two modes
DecoratorAwareBeanFactoryPostProcessoraccepts two runtime modes. The 'processor' (default) mode uses
DecoratorChainingStrategyto wire the decorator chain. The 'resolver' mode uses
DecoratorAwareAutowireCandidateResolverto implement custom wiring logic based on complex wiring rules implemented in
ResolverCDIAutowiringRules. The 'resolver' mode was just another option how one can implement such complex logic. I tried two different options and both work. The 'processor' alternative however implements simpler logic. Therefore it's my prefered mode at the moment.
Decorator Meta Data Model
DecoratorAwareBeanFactoryPostProcessorscans bean definitions and stores meta data about the decorators and delegates in the application context. These are the model beans in their hierarchical access order:
DecoratorMetaDataBean.java: Top level entry point to the meta-data. Registered and available in the application context.
QualifiedDecoratorChain.java: A chain of decorators for the same target delegate bean.
DecoratorInfo.java: A decorator bean definition wrapper class.
DelegateField.java: Contains the delegate field of the decorator implementation.
The Spring-CDI decorator module is easy to adopt by users through the use of strategy pattern in many places. These are the strategies that allow users to change processing logic if required:
DecoratorChainingStrategy.java: Wires the decorators for a specific target delegate bean.
DecoratorOrderingStrategy.java: Orders the decorators for a specific target delegate bean.
DecoratorResolutionStrategy.java: Scans the bean factory for available decorator beans.
DelegateResolutionStrategy.java: Searches the delegate bean for a specific decorator bean.
Decorator Autowiring Rules
The 'processor' mode and the 'resolver' mode both use a custom
AutowireCandidateResolverapplied to the current bean factory. The class is called
DecoratorAwareAutowireCandidateResolverand it is applied to the bean factory in the
DecoratorAwareBeanFactoryPostProcessor. The custom resolver works with different rule sets. In the 'processor' mode it works with a very simple rule set called
BeanPostProcessorCDIAutowiringRules. In the 'resolver' mode it uses
ResolverCDIAutowiringRuleswhich is far more complex. If these rule sets are not sufficient for your autowiring logic, it's easy to apply additional rule sets by implementing a custom
SpringCDIPluginand adding it to the
Spring-CDI Plugin System
The Spring-CDI decorator module contains two infrastructure interfaces that allow the modularized approach of Spring-CDI project:
SpringCDIInfrastructure. When I implement additional modules - like the interceptor module - users can decide which modules to use and import into their projects. It's not required to add all Spring-CDI functionality if one only needs decorators.