added constructor bypassing instantiation
This commit is contained in:
@@ -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
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user