Created
June 23, 2016 14:09
-
-
Save johnou/03c3677cd72f40d3778ea1f7b39df9d3 to your computer and use it in GitHub Desktop.
SpringActorClassFinder entire classpath
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cloud.orbit.actors.Actor; | |
import cloud.orbit.actors.Remindable; | |
import cloud.orbit.actors.extensions.ActorClassFinder; | |
import cloud.orbit.actors.runtime.ReminderController; | |
import cloud.orbit.actors.runtime.ReminderControllerActor; | |
import cloud.orbit.actors.streams.simple.SimpleStream; | |
import cloud.orbit.actors.streams.simple.SimpleStreamActor; | |
import org.apache.log4j.Logger; | |
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.beans.factory.config.BeanDefinition; | |
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; | |
import org.springframework.core.type.filter.AssignableTypeFilter; | |
import org.springframework.stereotype.Component; | |
import org.springframework.util.ClassUtils; | |
import javax.annotation.PostConstruct; | |
import java.util.*; | |
import java.util.function.Predicate; | |
/** | |
* {@link SpringActorClassFinder} uses Spring utility classes to locate actor implementations. | |
* | |
* @author Johno Crawford ([email protected]) | |
*/ | |
@Component | |
public class SpringActorClassFinder implements ActorClassFinder { | |
private static final Logger logger = Logger.getLogger(SpringActorClassFinder.class); | |
@Autowired | |
private ActorImplementationProvider actorImplementationProvider; | |
private Map<Class<?>, Class<?>> concreteImplementations = new HashMap<>(); | |
@PostConstruct | |
public void initialize() { | |
long start = System.currentTimeMillis(); | |
Map<Class<?>, Class<?>> implementations = actorImplementationProvider.getActorImplementations(); | |
logger.info("Took " + (System.currentTimeMillis() - start) + "ms to scan for Actor implementations."); | |
implementations.put(ReminderController.class, ReminderControllerActor.class); // built in Orbit actor | |
implementations.put(SimpleStream.class, SimpleStreamActor.class); // built in Orbit actor | |
this.concreteImplementations = implementations; | |
} | |
@Override | |
@SuppressWarnings("unchecked") | |
public <T extends Actor> Class<? extends T> findActorImplementation(Class<T> clazz) { | |
return (Class<T>) concreteImplementations.get(clazz); | |
} | |
@Override | |
public <T extends Actor> Collection<Class<? extends T>> findActorInterfaces(Predicate<Class<T>> predicate) { | |
List<Class<? extends T>> interfaces = null; | |
for (Class<?> concreteInterface : concreteImplementations.keySet()) | |
{ | |
if (predicate.test((Class<T>) concreteInterface)) | |
{ | |
if (interfaces == null) { | |
interfaces = new ArrayList<>(); | |
} | |
interfaces.add((Class<T>) concreteInterface); | |
} | |
} | |
return interfaces != null ? interfaces : Collections.emptyList(); | |
} | |
@Component | |
private class ActorImplementationProvider extends ClassPathScanningCandidateComponentProvider { | |
@Autowired | |
public ActorImplementationProvider() { | |
super(false); | |
addIncludeFilter(new AssignableTypeFilter(Actor.class)); | |
} | |
public Map<Class<?>, Class<?>> getActorImplementations() { | |
List<Class<?>> clazzImplementations = new ArrayList<>(); | |
Map<Class<?>, Class<?>> actorImplementations = new HashMap<>(); | |
for (BeanDefinition candidate : findCandidateComponents("")) { | |
Class<?> implementation = ClassUtils.resolveClassName(candidate.getBeanClassName(), ClassUtils.getDefaultClassLoader()); | |
clazzImplementations.add(implementation); | |
} | |
for (Class<?> clazzImplementation : clazzImplementations) { | |
Class<?>[] implementationInterfaces = clazzImplementation.getInterfaces(); // check interfaces directly to support inheritance | |
if (implementationInterfaces.length == 0) { | |
continue; | |
} | |
for (Class<?> implementationInterface : implementationInterfaces) { | |
if (implementationInterface == Remindable.class) { | |
continue; | |
} | |
if (Actor.class.isAssignableFrom(implementationInterface)) { | |
Class<?> old = actorImplementations.put(implementationInterface, clazzImplementation); | |
if (old != null) { | |
logger.warn("Multiple actor implementations found for " + implementationInterface); | |
} | |
} | |
} | |
} | |
return actorImplementations; | |
} | |
@Override | |
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { | |
return beanDefinition.getMetadata().isConcrete(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment