cache warmup abstraction with @Preload
This commit is contained in:
Родитель
fbb92c5268
Коммит
95b4593bb3
|
@ -89,6 +89,10 @@
|
|||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>adal4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.toolkit.lib.common.cache;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* to annotate methods that should be pre-executed at background
|
||||
* the annotated method should have no args and must be static or in a singleton class
|
||||
*/
|
||||
@Target(value = {ElementType.METHOD})
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Preload {
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.toolkit.lib.common.cache;
|
||||
|
||||
import lombok.extern.java.Log;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.MethodAnnotationsScanner;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@Log
|
||||
public class Preloader {
|
||||
|
||||
private static final String INVALID_PRELOAD_METHOD = "@Preload annotated method(%s.%s) should have (no args or only varargs) " +
|
||||
"and must be (static or in a singleton class)";
|
||||
|
||||
public static Collection<Method> load() {
|
||||
final Set<Method> methods = getPreloadingMethods();
|
||||
log.log(Level.INFO, String.format("Found %d @Preload annotated methods.", methods.size()));
|
||||
methods.parallelStream().forEach((m) -> {
|
||||
Object instance = null;
|
||||
// TODO: maybe support predefined variables, e.g. selected subscriptions
|
||||
if ((m.getParameterCount() == 0 || m.isVarArgs())
|
||||
&& (Modifier.isStatic(m.getModifiers()) || Objects.nonNull(instance = getSingleton(m)))) {
|
||||
invoke(m, instance);
|
||||
} else {
|
||||
log.warning(String.format(INVALID_PRELOAD_METHOD, m.getDeclaringClass().getSimpleName(), m.getName()));
|
||||
}
|
||||
});
|
||||
return methods;
|
||||
}
|
||||
|
||||
private static void invoke(final Method m, final Object instance) {
|
||||
try {
|
||||
if (m.isVarArgs()) {
|
||||
final Class<?> varargType = m.getParameterTypes()[0].getComponentType();
|
||||
m.invoke(instance, Array.newInstance(varargType, 0));
|
||||
} else {
|
||||
m.invoke(instance);
|
||||
}
|
||||
} catch (final IllegalAccessException | InvocationTargetException ignored) {
|
||||
// swallow all exceptions
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getSingleton(final Method m) {
|
||||
final Class<?> clazz = m.getDeclaringClass();
|
||||
try {
|
||||
final Method getInstance = clazz.getDeclaredMethod("getInstance");
|
||||
if (Modifier.isStatic(getInstance.getModifiers()) && getInstance.getParameterCount() == 0) {
|
||||
getInstance.setAccessible(true);
|
||||
return getInstance.invoke(null);
|
||||
}
|
||||
} catch (final IllegalAccessException | InvocationTargetException | NoSuchMethodException ignored) {
|
||||
// swallow all exceptions
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Set<Method> getPreloadingMethods() {
|
||||
final ConfigurationBuilder configuration = new ConfigurationBuilder()
|
||||
.forPackages("com.microsoft.azure.toolkit")
|
||||
.setScanners(new MethodAnnotationsScanner());
|
||||
final Reflections reflections = new Reflections(configuration);
|
||||
return reflections.getMethodsAnnotatedWith(Preload.class);
|
||||
}
|
||||
}
|
|
@ -97,6 +97,7 @@
|
|||
<google.jsr305.version>3.0.0</google.jsr305.version>
|
||||
<free.port.finder.version>1.0</free.port.finder.version>
|
||||
<jjwt.version>0.9.1</jjwt.version>
|
||||
<reflections.version>0.9.12</reflections.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -279,6 +280,11 @@
|
|||
<artifactId>commons-collections4</artifactId>
|
||||
<version>${commons.collections4.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>${reflections.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
|
|
Загрузка…
Ссылка в новой задаче