我正在尝试在运行时生成类型化类的实例以使用redis。
这是我的代码,但是它无法创建类型化类T的实例。
interface ObjectFactory<T>
{
T create() throws Exception;
}
这是创建T
实例的类import java.lang.reflect.ParameterizedType;
public class RedisObjectConstructor<T> implements ObjectFactory<T>
{
@SuppressWarnings("unchecked")
@Override
public T create() throws Exception
{
try
{
return (T) ((Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
}
catch (Exception e)
{
throw new Exception();
}
}
}
这是实际设置和获取域字段值的逻辑:
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.stereotype.Component;
@Component
public class RedisBasicEntity<T>
{
private final ObjectFactory<T> factory;
public RedisBasicEntity(ObjectFactory<T> factory)
{
this.factory = factory;
}
public Map<String, String> getFields(T redisDomain, Class<? extends Annotation> ann)
{
Map<String, String> redisHash = new HashMap<String, String>();
Class<?> clazz = redisDomain.getClass();
while (clazz != null)
{
for (Field field : clazz.getDeclaredFields())
{
if (field.isAnnotationPresent(ann))
{
field.setAccessible(true);
try
{
Object value = field.get(redisDomain);
if (value != null)
{
redisHash.put(field.getName(), value.toString());
System.out.println(field.getName() + ":" + value.toString());
}
}
catch (IllegalArgumentException e)
{
}
catch (IllegalAccessException e)
{
}
}
}
c = c.getSuperclass();
}
return redisHash;
}
public T getRedisEntity(Map<String, String> redisHash, Class<? extends Annotation> ann) throws Exception
{
T redisDomain = factory.create();
Class<?> clazz = redisDomain.getClass();
while (clazz != null)
{
for (Field field : clazz.getDeclaredFields())
{
if (field.isAnnotationPresent(ann))
{
field.setAccessible(true);
try
{
FieldUtils.writeDeclaredField(field, field.getName(), redisHash.get(field.getName()));
}
catch (Exception e)
{
}
}
}
}
return redisDomain;
}
}
这是我的测试类:
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import com.ranker.annotations.rediskey.RedisHashKey;
import com.ranker.api.dao.iListQualityDAO;
import com.ranker.app.redis.domain.list.ListQuality;
import com.ranker.app.redis.repository.support.RedisBasicEntity;
import com.ranker.app.redis.repository.support.RedisObjectConstructor;
public class ListQualityDAO implements iListQualityDAO
{
@Autowired
private RedisBasicEntity<ListQuality> redisBasicEntity;
public static ListQuality saveListQuality()
{
RedisObjectConstructor<ListQuality> redisObjectConstructor = new RedisObjectConstructor<ListQuality>();
RedisBasicEntity<ListQuality> redisBasicEntity = new RedisBasicEntity<ListQuality>(redisObjectConstructor);
ListQuality listQuality = new ListQuality();
listQuality.setBurialScore(10.0);
Map<String, String> redisHash = redisBasicEntity.getFields(listQuality, RedisHashKey.class);
return null;
}
public static ListQuality getListQuality() throws Exception
{
RedisObjectConstructor<ListQuality> redisObjectConstructor = new RedisObjectConstructor<ListQuality>();
RedisBasicEntity<ListQuality> redisBasicEntity = new RedisBasicEntity<ListQuality>(redisObjectConstructor);
Map<String, String> redisHash = new HashMap<String, String>();
redisHash.put("satisfactionScore", "10.00");
redisHash.put("burialScore", "5.00");
redisHash.put("burialState", "true");
ListQuality listQuality = redisBasicEntity.getRedisEntity(redisHash, RedisHashKey.class);
return listQuality;
}
public static void main(String args[]) throws Exception
{
ListQualityDAO.getListQuality();
}
}
用于识别字段的我的注释:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisHashKey {
}
请告诉我这里的错误:
以下是我测试运行时的异常:
线程中的异常&#34; main&#34; java.lang.Exception at com.ranker.app.redis.repository.support.RedisObjectConstructor.create(RedisObjectConstructor.java:19) 在 com.ranker.app.redis.repository.support.RedisBasicEntity.getRedisEntity(RedisBasicEntity.java:61) 在 com.ranker.api.dao.impl.ListQualityDAO.getListQuality(ListQualityDAO.java:37) 在 com.ranker.api.dao.impl.ListQualityDAO.main(ListQualityDAO.java:45)
答案 0 :(得分:1)
使用TypeTools,您的Class<T> type = (Class<T>)TypeResolver.resolveRawArgument(ObjectFactory.class, getClass());
return type.newInstance();
实施可以是:
T
注意:这仅适用于您在此类中使用实际值参数化class RedisStringConstructor extends RedisObjectConstructor<String> { //...
的类。例如:
String
这样,类型参数RedisObjectConstructor
保留在字节码中,可以恢复。简单地使用某种类型参数实例化new RedisObjectConstructor<String>(); // can't recover String
将不允许它被恢复:
ACC.NBR,CTA.NAMEZ
答案 1 :(得分:0)
正如此stackoverflow response中所述,我以这种方式修改了create
的{{1}}方法:
RedisObjectConstructor<T>
并像这样实现它:
public class RedisObjectConstructor<T> implements ObjectFactory<T> {
private final Class<T> type;
public RedisObjectConstructor(Class<T> type) {
this.type = type;
}
@Override
public T create() throws Exception {
return type.newInstance();
}
}
并且没有更多的强制转换异常问题。