in archaius2-core/src/main/java/com/netflix/archaius/ConfigProxyFactory.java [310:358]
private <T> MethodInvokerHolder buildInvokerForMethod(Class<T> proxyObjectType, String prefix, Method m, T proxyObject, boolean immutable) {
try {
final Class<?> returnType = m.getReturnType();
final PropertyName nameAnnot = m.getAnnotation(PropertyName.class);
final String propName = getPropertyName(prefix, m, nameAnnot);
// A supplier for the value to be returned when the method's associated property is not set
// The proper parametrized type for this would be Function<Object[], returnType>, but we can't say that in Java.
final Function<Object[], ?> defaultValueSupplier = defaultValueSupplierForMethod(proxyObjectType, m, returnType, proxyObject, propName);
// This object encapsulates the way to get the value for the current property.
final PropertyValueGetter propertyValueGetter;
if (!knownCollections.containsKey(returnType)
&& returnType.isInterface()
&& !(decoder instanceof TypeConverter.Registry && ((TypeConverter.Registry) decoder).get(m.getGenericReturnType()).isPresent())) {
// Our return type is an interface but not a known collection and is also not a type our decoder can handle.
// We treat it as a nested Config proxy interface and create a proxy with it, with the current property name as the initial prefix for nesting.
propertyValueGetter = createInterfaceProperty(propName, newProxy(returnType, propName, immutable));
} else if (m.getParameterCount() > 0) {
// A parameterized property. Note that this requires a @PropertyName annotation to extract the interpolation positions!
if (nameAnnot == null) {
throw new IllegalArgumentException("Missing @PropertyName annotation on method with parameters " + m.getName());
}
// A previous version allowed the full name to be specified, even if the prefix was specified. So, for
// backwards compatibility, we allow both including or excluding the prefix for parameterized names.
String propertyNameTemplate;
if (!StringUtils.isBlank(prefix) && !nameAnnot.name().startsWith(prefix)) {
propertyNameTemplate = prefix + nameAnnot.name();
} else {
propertyNameTemplate = nameAnnot.name();
}
// TODO: Figure out a way to validate the template. It should have params in the form ${0}, ${1}, etc.
propertyValueGetter = createParameterizedProperty(m.getGenericReturnType(), propertyNameTemplate, defaultValueSupplier);
} else {
// Anything else.
propertyValueGetter = createScalarProperty(m.getGenericReturnType(), propName, defaultValueSupplier);
}
return new MethodInvokerHolder(propertyValueGetter, propName);
} catch (RuntimeException e) {
throw new RuntimeException("Failed to create a proxy for method " + m.getName() + ": " + e, e);
}
}