add logic to singleton test

refactor internal workings in sdicontainer
master
Josha von Gizycki 7 years ago
parent 2dbc4a5806
commit f94e86df1d

@ -56,7 +56,10 @@ class IntegrityCheck {
LOG.info("found service class for name {}: {}", key, value);
try {
Class<?> clz = Class.forName(value);
definitions.add(new ServiceDefinition().setClz(clz).setName(value));
definitions.add(new ServiceDefinition()
.setClz(clz)
.setName(key)
.setSingleton(isSingleton(key)));
return clz;
} catch (ClassNotFoundException e) {
throw new SdicClassNotFound(e);
@ -64,6 +67,11 @@ class IntegrityCheck {
}).collect(Collectors.toList());
}
private boolean isSingleton(String name) {
return props.containsKey(name + ".singleton") && "true"
.equals(props.get(name + ".singleton"));
}
private void checkConstructorDependencies(List<Class<?>> services) {
services.stream()
// get the first and only constructor

@ -9,9 +9,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -19,20 +17,20 @@ public class SdiContainer implements SdiContainerInterface {
private static final Logger LOG = LoggerFactory.getLogger(SdiContainer.class);
private final Properties props;
private final List<ServiceDefinition> definitions;
private final Map<Class<?>, Object> singletons;
private final Map<ServiceDefinition, Object> singletons;
private SdiContainer(Properties props, List<ServiceDefinition> definitions) {
this.props = props;
private SdiContainer(List<ServiceDefinition> definitions) {
this.definitions = definitions;
this.singletons = new HashMap<>();
}
@SuppressWarnings("unused")
public static SdiContainer load() {
return load("sdic.properties");
}
@SuppressWarnings("WeakerAccess")
public static SdiContainer load(String filename) {
Properties props = new Properties();
@ -49,47 +47,47 @@ public class SdiContainer implements SdiContainerInterface {
IntegrityCheck integrityCheck = new IntegrityCheck(props);
integrityCheck.check();
return new SdiContainer(props, integrityCheck.getDefinitions());
return new SdiContainer(integrityCheck.getDefinitions());
}
private List<Class<?>> serviceClasses() {
return definitions.stream().map(ServiceDefinition::getClz).collect(Collectors.toList());
private <T> ServiceDefinition getDefinition(Class<T> clz) {
return definitions.stream()
.filter(d -> d.getClz() == clz)
.findFirst()
.orElse(null);
}
@Override
public <T> T getInstance(Class<T> clz) {
LOG.trace("instance ordered: ", clz);
if (!serviceClasses().contains(clz)) {
ServiceDefinition definition = getDefinition(clz);
if (definition == null) {
throw new ClassNotRegistered(clz);
}
if (isStoredAsSingleton(clz)) {
return clz.cast(singletons.get(clz));
LOG.debug("service name is {}", definition.getName());
if (isStoredAsSingleton(definition)) {
return clz.cast(singletons.get(definition));
}
try {
T instance = new Instantiator<>(clz, this).createInstance();
handleSingleton(clz, instance);
handleSingleton(definition, instance);
return instance;
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
throw new SdicInstantiationException(e);
}
}
private <T> void handleSingleton(Class<T> clz, T instance) {
String key = props.entrySet().stream()
.filter(e -> Objects.equals(clz.getName(), String.valueOf(e.getValue())))
.map(e -> e.getKey().toString())
.findFirst()
.orElse("");
if (props.containsKey(key + ".singleton") && "true".equals(props.get(key + ".singleton"))) {
singletons.put(clz, instance);
private <T> void handleSingleton(ServiceDefinition definition, T instance) {
if (definition.isSingleton()) {
singletons.put(definition, instance);
}
}
private <T> boolean isStoredAsSingleton(Class<T> clz) {
return singletons.containsKey(clz);
private boolean isStoredAsSingleton(ServiceDefinition def) {
return singletons.containsKey(def);
}
}

@ -1,5 +1,6 @@
package de.joshavg.simpledic;
@SuppressWarnings("WeakerAccess")
public interface SdiContainerInterface {
<T> T getInstance(Class<T> clz);

@ -7,31 +7,73 @@ class ServiceDefinition {
private Class<?> clz;
private String name;
private Constructor<?> constructor;
private boolean isSingleton;
public Class<?> getClz() {
Class<?> getClz() {
return clz;
}
public ServiceDefinition setClz(Class<?> clz) {
ServiceDefinition setClz(Class<?> clz) {
this.clz = clz;
return this;
}
public String getName() {
String getName() {
return name;
}
public ServiceDefinition setName(String name) {
ServiceDefinition setName(String name) {
this.name = name;
return this;
}
public Constructor<?> getConstructor() {
Constructor getConstructor() {
return constructor;
}
public ServiceDefinition setConstructor(Constructor<?> constructor) {
ServiceDefinition setConstructor(Constructor<?> constructor) {
this.constructor = constructor;
return this;
}
boolean isSingleton() {
return isSingleton;
}
ServiceDefinition setSingleton(boolean singleton) {
isSingleton = singleton;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ServiceDefinition that = (ServiceDefinition) o;
if (isSingleton != that.isSingleton) {
return false;
}
if (!clz.equals(that.clz)) {
return false;
}
if (!name.equals(that.name)) {
return false;
}
return constructor.equals(that.constructor);
}
@Override
public int hashCode() {
int result = clz.hashCode();
result = 31 * result + name.hashCode();
result = 31 * result + constructor.hashCode();
result = 31 * result + (isSingleton ? 1 : 0);
return result;
}
}

@ -1,8 +1,10 @@
package de.joshavg.simpledic;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat;
import de.joshavg.simpledic.services.DependsOnNoDependencies;
import de.joshavg.simpledic.services.NoDependencies;
import org.junit.Test;
@ -15,4 +17,15 @@ public class SingletonTest {
sameInstance(container.getInstance(NoDependencies.class)));
}
@Test
public void sameInstanceViaDependency() {
SdiContainer container = SdiContainer.load("singleton.properties");
DependsOnNoDependencies i1 = container.getInstance(DependsOnNoDependencies.class);
DependsOnNoDependencies i2 = container.getInstance(DependsOnNoDependencies.class);
assertThat(i1, not(sameInstance(i2)));
assertThat(i1.getDependency(), sameInstance(i2.getDependency()));
}
}

@ -1,6 +1,14 @@
package de.joshavg.simpledic.services;
public class DependsOnNoDependencies {
private final NoDependencies b;
public DependsOnNoDependencies(NoDependencies b) {
this.b = b;
}
public NoDependencies getDependency() {
return b;
}
}

@ -1,2 +1,4 @@
service.one: de.joshavg.simpledic.services.NoDependencies
service.one.singleton: true
service.two: de.joshavg.simpledic.services.DependsOnNoDependencies

Loading…
Cancel
Save