Browse Source

added constructor bypassing instantiation

pull/2/head
Michael Hunger 15 years ago
parent
commit
2cbb372de5
  1. 38
      spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java

38
spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java

@ -3,6 +3,7 @@ package org.springframework.data.persistence; @@ -3,6 +3,7 @@ package org.springframework.data.persistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@ -20,7 +21,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S @@ -20,7 +21,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
private final Logger log = LoggerFactory.getLogger(getClass());
private final Map<Class<? extends BACKING_INTERFACE>,StateBackedCreator<? extends BACKING_INTERFACE,STATE>> cache = new HashMap<Class<? extends BACKING_INTERFACE>,StateBackedCreator<? extends BACKING_INTERFACE,STATE>>();
final public <T extends BACKING_INTERFACE> T createEntityFromState(STATE n, Class<T> c) {
public <T extends BACKING_INTERFACE> T createEntityFromState(STATE n, Class<T> c) {
try {
StateBackedCreator<T, STATE> creator = (StateBackedCreator<T, STATE>) cache.get(c);
if (creator !=null) return creator.create(n,c);
@ -47,34 +48,34 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S @@ -47,34 +48,34 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
}
protected <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> createInstantiator(Class<T> type, final Class<STATE> stateType) {
StateBackedCreator<T,STATE> creator =stateTakingConstructorInstantiator(type,stateType);
StateBackedCreator<T,STATE> creator = stateTakingConstructorInstantiator(type,stateType);
if (creator !=null) return creator;
creator = emptyConstructorStateSettingInstantiator(type,stateType);
if (creator !=null) return creator;
return createFailingInstantiator(stateType);
}
private <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> createFailingInstantiator(final Class<STATE> stateType) {
protected <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> createFailingInstantiator(final Class<STATE> stateType) {
return new StateBackedCreator<T, STATE>() {
public T create(STATE n, Class<T> c) throws Exception {
public T create(STATE state, Class<T> c) throws Exception {
throw new IllegalArgumentException(getClass().getSimpleName() + ": entity " + c +
" must have either a constructor taking [" + stateType + "] or a no-arg constructor and state set method");
}
};
}
private <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> emptyConstructorStateSettingInstantiator(Class<T> type, Class<STATE> stateType) {
protected <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> emptyConstructorStateSettingInstantiator(Class<T> type, Class<STATE> stateType) {
final Constructor<T> constructor = getNoArgConstructor(type);
if (constructor == null) return null;
log.info("Using " + type + " no-arg constructor");
return new StateBackedCreator<T, STATE>() {
public T create(STATE n, Class<T> c) throws Exception {
public T create(STATE state, Class<T> c) throws Exception {
try {
StateProvider.setUnderlyingState(n);
StateProvider.setUnderlyingState(state);
T newInstance = constructor.newInstance();
setState(newInstance, n);
setState(newInstance, state);
return newInstance;
} finally {
StateProvider.retrieveState();
@ -83,13 +84,28 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S @@ -83,13 +84,28 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
};
}
private <T extends BACKING_INTERFACE> Constructor<T> getNoArgConstructor(Class<T> type) {
@SuppressWarnings("unchecked")
protected <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> createWithoutConstructorInvocation(final Class<T> type, Class<STATE> stateType) {
ReflectionFactory rf = ReflectionFactory.getReflectionFactory();
Constructor<?> objectConstructor = getDeclaredConstructor(Object.class);
final Constructor<?> serializationConstructor = rf.newConstructorForSerialization(type, objectConstructor);
return new StateBackedCreator<T, STATE>() {
public T create(STATE state, Class<T> c) throws Exception {
final T result = type.cast(serializationConstructor.newInstance());
setState(result,state);
return result;
}
};
}
protected <T extends BACKING_INTERFACE> Constructor<T> getNoArgConstructor(Class<T> type) {
Constructor<T> constructor = ClassUtils.getConstructorIfAvailable(type);
if (constructor != null) return constructor;
return getDeclaredConstructor(type);
}
private <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> stateTakingConstructorInstantiator(Class<T> type, Class<STATE> stateType) {
protected <T extends BACKING_INTERFACE> StateBackedCreator<T, STATE> stateTakingConstructorInstantiator(Class<T> type, Class<STATE> stateType) {
Class<? extends STATE> stateInterface = (Class<? extends STATE>) stateType.getInterfaces()[0];
final Constructor<T> constructor = ClassUtils.getConstructorIfAvailable(type, stateInterface);
if (constructor == null) return null;
@ -102,7 +118,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S @@ -102,7 +118,7 @@ public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, S
};
}
private <T> Constructor<T> getDeclaredConstructor(Class<T> c) {
protected <T> Constructor<T> getDeclaredConstructor(Class<T> c) {
try {
final Constructor<T> declaredConstructor = c.getDeclaredConstructor();
declaredConstructor.setAccessible(true);

Loading…
Cancel
Save