
Utilities
This contains shared, general-purpose helper classes and annotations. It contains two metadata classes, one to represent an annotaion, the AnnotationLiteral, and one to represent a type. An AnnotationLiteral represents an annotation as an abstract class and it is used mainly for manual injection through the BeanManager:
Set<Bean<?>> beans = beanManager.getBeans(ConfigurationBean.class, new AnnotationLiteral<Default>() {});
Here's a representation of a named annotation as AnnotationLiteral:
public class NamedAnnotation extends AnnotationLiteral<Named> implements Named {
private final String value;
public NamedAnnotation(final String value) {
this.value = value;
}
public String value() {
return value;
}
}
The same goes for the TypeLiteral; you can represent a typed annotation as an abstract class. You can use it over than a manual injection, to create a list with declared types. Here is a sample:
TypeLiteral listBooleans = new TypeLiteral<List<Boolean>>() {};
List<Type> types = asList(Integer.class, String.class, listBooleans);
The util package provides an annotation too, Nonbinding. It can exclude a member of an annotation type (for example, an interceptor binding type or a qualifier type) when the container must compare two annotation instances. See these elements as an example. Here's an enum:
public enum ConfigurationKey {
DEFAULT_DIRECTORY, VERSION, BUILD_TIMESTAMP, PRODUCER
}
The following is a qualifier marked with the @Nonbinding annotation:
@Target({ FIELD, METHOD })
@Retention(RUNTIME)
@Qualifier
public @interface ConfigurationValue {
@Nonbinding
ConfigurationKey key();
}
We will inject a String qualified by the parametric annotation @ConfigurationValue:
@Inject
@ConfigurationValue(key = DEFAULT_DIRECTORY)
private String defaultDirectory;
At the same time, we have a produces method for the String qualified by @ConfigurationValue but with a different key:
@Produces
@ConfigurationValue(key = PRODUCER)
public String produceConfigurationValue(InjectionPoint injectionPoint) {
Annotated annotated = injectionPoint.getAnnotated();
ConfigurationValue annotation = annotated.getAnnotation(ConfigurationValue.class);
if (annotation != null) {
ConfigurationKey key = annotation.key();
if (key != null) {
switch (key) {
case DEFAULT_DIRECTORY:
return "/user/test";
case VERSION:
return "2.3.4";
case BUILD_TIMESTAMP:
return "10-10-2016:10:10:10";
default:
return null;
}
}
}
throw new IllegalStateException("No key for injection point: " + injectionPoint);
}
The value of the injected defaultDirectory will be: /user/test. In this case if we delete the @Nonbinding annotation in ConfigurationValue, defaultDirectory will never be enhanced because the producer method will be active only for the key = PRODUCER. So, thanks to @Nonbinding, the comparison of the ConfigurationKey enum is never done.