-
Notifications
You must be signed in to change notification settings - Fork 2
Extending Pinject
Pinject is easily extended to meet the specific needs of your application. You can provide your own resolvers to handle property resolution from resources other than simple properties files, and you can provide your own converters to handle injection point data types that are not among those handled by the built-in converters. Your extensions are loaded by Pinject using the ServiceLoader mechanism introduced in JDK 6.
You can augment the built-in property resolvers by supplying your own.
- Create a class that implements PropertyResolver.
- Place a file in
META-INF/services
on the classpath with the nameorg.soulwing.cdi.properties.spi.PropertyResolver
and add the fully-qualified class name(s) of your resolvers(s), one per line.
Each resolver has a priority that determines the order in which resolvers will be consulted during property name resolution -- resolvers with larger numeric values of priority will be consulted before those with smaller values.
The built-in resolvers have priority values between -10 and -1. Your resolver can use any positive value of priority to override the built-in resolvers. If your resolver uses a value less than -10 it will be consulted after the built-in resolvers, but before the last resort use of the default value specified on the @Property
qualifier.
The init
and destroy
lifecycle methods of a resolver should be used to establish and teardown, respectively, whatever resources (e.g. database connections) your resolver implementation may require.
Unfortunately, because your resolver will be participating in the processes that support bean creation and dependency injection, your resolver cannot be designed to use the facilities of CDI in its own implementation.
Other value types with well-defined string representations are easily supported by defining your own converter extension.
- Create a class that implements PropertyConverter.
- Place a file in
META-INF/services
on the classpath with the nameorg.soulwing.cdi.properties.spi.PropertyConverter
and add the fully-qualified class name(s) of your converter(s), one per line.
Converters are consulted (in an arbitrary order) until one is found which claims to support the type of the injection target.
A given converter can support more than one type -- the target type of the injection point is provided as context when the converter is called upon to convert a property value. The context also provides the means to invoke other converters, which is useful when converting compound types.
Every converter has a name. The names of the converters included with Pinject are set to the fully qualified converter class name. You can request that an injection point use a specific converter (by name) using the converter
attribute of the @Property
qualifier. This is useful if you want to override one of the built-in converters in some specific case(s).
Unfortunately, because your converter will be participating in the processes that support bean creation and dependency injection, your converter cannot be designed to use the facilities of CDI in its own implementation.
The SPI provides the Optional interface which can be implemented by resolver and converter extensions that depend on libraries or other resources which may not always be available in the runtime environment. A resolver or converter that implements this interface is given an opportunity to inspect the runtime environment to determine whether it can be used successfully.
Before initializing an Optional
resolver or converter, Pinject invokes the isAvailable
method to allow your extension to check whether its runtime dependencies can be satisified. If (and only if) your extension returns true
, it is subsequently initialized and used by Pinject to resolve or convert property values.