Create delayed injection test runner
- Test runner supporting new "DelayedInjection" annotation: such fields are only initialized with instantiation right before the first time they're used in tests, allowing to set up mock behavior beforehand
This commit is contained in:
@@ -5,7 +5,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import fr.xephi.authme.settings.NewSetting;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Provider;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -167,8 +166,7 @@ public class AuthMeServiceInitializer {
|
||||
* @return the instantiated object
|
||||
*/
|
||||
private <T> T instantiate(Class<T> clazz, Set<Class<?>> traversedClasses) {
|
||||
Injection<T> injection = firstNotNull(
|
||||
ConstructorInjection.provide(clazz), FieldInjection.provide(clazz), InstantiationFallback.provide(clazz));
|
||||
Injection<T> injection = InjectionHelper.getInjection(clazz);
|
||||
if (injection == null) {
|
||||
throw new IllegalStateException("Did not find injection method for " + clazz + ". Make sure you have "
|
||||
+ "a constructor with @Inject or fields with @Inject. Fields with @Inject require "
|
||||
@@ -268,7 +266,7 @@ public class AuthMeServiceInitializer {
|
||||
* @param object the object to execute the post construct method for
|
||||
*/
|
||||
private static void executePostConstructMethod(Object object) {
|
||||
Method postConstructMethod = getAndValidatePostConstructMethod(object.getClass());
|
||||
Method postConstructMethod = InjectionHelper.getAndValidatePostConstructMethod(object.getClass());
|
||||
if (postConstructMethod != null) {
|
||||
try {
|
||||
postConstructMethod.setAccessible(true);
|
||||
@@ -285,40 +283,4 @@ public class AuthMeServiceInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and locate the given class' post construct method. Returns {@code null} if none present.
|
||||
*
|
||||
* @param clazz the class to search
|
||||
* @return post construct method, or null
|
||||
*/
|
||||
private static Method getAndValidatePostConstructMethod(Class<?> clazz) {
|
||||
Method postConstructMethod = null;
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (method.isAnnotationPresent(PostConstruct.class)) {
|
||||
if (postConstructMethod != null) {
|
||||
throw new IllegalStateException("Multiple methods with @PostConstruct on " + clazz);
|
||||
} else if (method.getParameterTypes().length > 0 || Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@PostConstruct method may not be static or have any parameters. "
|
||||
+ "Invalid method in " + clazz);
|
||||
} else if (method.getReturnType() != void.class) {
|
||||
throw new IllegalStateException("@PostConstruct method must have return type void. "
|
||||
+ "Offending class: " + clazz);
|
||||
} else {
|
||||
postConstructMethod = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return postConstructMethod;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static <T> Injection<T> firstNotNull(Provider<? extends Injection<T>>... providers) {
|
||||
for (Provider<? extends Injection<T>> provider : providers) {
|
||||
Injection<T> object = provider.get();
|
||||
if (object != null) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
/**
|
||||
* Functionality for constructor injection.
|
||||
*/
|
||||
public class ConstructorInjection<T> implements Injection<T> {
|
||||
class ConstructorInjection<T> implements Injection<T> {
|
||||
|
||||
private final Constructor<T> constructor;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
/**
|
||||
* Functionality for field injection.
|
||||
*/
|
||||
public class FieldInjection<T> implements Injection<T> {
|
||||
class FieldInjection<T> implements Injection<T> {
|
||||
|
||||
private final Field[] fields;
|
||||
private final Constructor<T> defaultConstructor;
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package fr.xephi.authme.initialization;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Provider;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* Helper class for functions relating to injecting.
|
||||
*/
|
||||
public class InjectionHelper {
|
||||
|
||||
private InjectionHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Injection} for the given class, or null if none applicable.
|
||||
*
|
||||
* @param clazz the class to process
|
||||
* @param <T> the class' type
|
||||
* @return injection of the class or null if none detected
|
||||
*/
|
||||
public static <T> Injection<T> getInjection(Class<T> clazz) {
|
||||
return firstNotNull(
|
||||
ConstructorInjection.provide(clazz),
|
||||
FieldInjection.provide(clazz),
|
||||
InstantiationFallback.provide(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and locates the given class' post construct method. Returns {@code null} if none present.
|
||||
*
|
||||
* @param clazz the class to search
|
||||
* @return post construct method, or null
|
||||
*/
|
||||
public static Method getAndValidatePostConstructMethod(Class<?> clazz) {
|
||||
Method postConstructMethod = null;
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (method.isAnnotationPresent(PostConstruct.class)) {
|
||||
if (postConstructMethod != null) {
|
||||
throw new IllegalStateException("Multiple methods with @PostConstruct on " + clazz);
|
||||
} else if (method.getParameterTypes().length > 0 || Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@PostConstruct method may not be static or have any parameters. "
|
||||
+ "Invalid method in " + clazz);
|
||||
} else if (method.getReturnType() != void.class) {
|
||||
throw new IllegalStateException("@PostConstruct method must have return type void. "
|
||||
+ "Offending class: " + clazz);
|
||||
} else {
|
||||
postConstructMethod = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return postConstructMethod;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static <T> Injection<T> firstNotNull(Provider<? extends Injection<T>>... providers) {
|
||||
for (Provider<? extends Injection<T>> provider : providers) {
|
||||
Injection<T> object = provider.get();
|
||||
if (object != null) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
* Fallback instantiation method for classes with an accessible no-args constructor
|
||||
* and no elements whatsoever annotated with {@link Inject} or {@link PostConstruct}.
|
||||
*/
|
||||
public class InstantiationFallback<T> implements Injection<T> {
|
||||
class InstantiationFallback<T> implements Injection<T> {
|
||||
|
||||
private final Constructor<T> constructor;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user