如何加快反思代码?

时间:2014-05-30 00:44:07

标签: java performance reflection

在我的应用程序中,我使用Apache的DBUtils类从MySQL数据库中读取。我编写了一个自定义的BasicRowProcessor,它使用数据对象字段上的注释来读取数据库中的列。它在代码方面非常有效,但是当我拉大量行时,性能相当慢。例如,使用此代码,1500行x 35列结果集将花费800毫秒,但如果我使用标准JDBC代码,则只需80毫秒。

问题 - 我该怎么做才能加快这段代码的速度?具体来说,我使用了大量的反思和注释 - 我是否缺少加快速度的技巧?

 @Override
   public <T> T toBean(ResultSet rs, Class<T> type) throws SQLException
   {
         T data = type.newInstance();

         Field[] f = type.getFields();

         for (int i=0; i<f.length; i++)
         {
            Field field = f[i];

            if (field.isAnnotationPresent(DBColumn.class))
            {
               String columnName = field.getAnnotation(DBColumn.class).name();
            }

            if (field.getType().getName().equals("int"))
            {
               field.setInt(data, rs.getInt(columnName));
            }
            else if (field.getType().getName().equals("long"))
            {
              field.setLong(data, rs.getLong(columnName));
            }
            // .... for all the other types

        }

    return data;
 }

2 个答案:

答案 0 :(得分:1)

也许是建立&amp;缓存行映射逻辑,因此您不必扫描字段,注释,结果集元数据和每次都有类型。

JDBC元数据访问速度特别慢。

在此示例中,您可以提供字符串“key”,以便为不同的结果集类型(不同的列结构)启用映射器的高效缓存。

public BasicRowProcessor getReflectiveRowMapper (ResultSet rs, String resultSetKey, Class<T> type) {
    String key = resultSetKey+"-"+type;
    BasicRowProcessor result = rrmCache.get( key);
    if (result != null) {
        result = buildReflectiveRowMapper (rs, resultSetKey, type);
        rrmCache.put( key, result);
    }
    return result;
}

public BuiltRowProcessor buildReflectiveRowMapper (ResultSet rs, String resultSetKey, Class<T> type) {
}

然后..

public class BuiltRowProcessor extends BasicRowProcessor {
    protected FieldMapping[] mappings;

    @Override
    public <T> T toBean (ResultSet rs, Class<T> type) throws SQLException {
        T data = type.newInstance();
        for (FieldMapping field : mappings) {
            field.mapField( rs, data);
        }
        return data;
    }
}

abstract public class FieldMapping {
    protected Field field;
    protected int columnIndex;

    // constructor..

    abstract public void mapField (ResultSet rs, Object target) throws SQLException;

    protected void writeField (Object target, Object value) {
        try {
            field.setValue(target, value);   // or whatever API.
        } catch (Exception x) {
            throw new RuntimeException("error writing field: "+field, x);
        }
    }
}

public IntMapping extends FieldMapping {
    // constructor..

    public void mapField (ResultSet rs, Object target) throws SQLException {
        int value = rs.getInt(columnIndex);
        writeField( target, value);
    }
}

答案 1 :(得分:0)

不要比较类型的名称。将类型与int.class,long.class等进行比较

事实上,你不需要所有这些&#39;如果&#39;声明。只需调用Field.set(),使用ResultSet.getObject()作为参数。所有正确的事情都会在内部发生。但我不会说这会更快。

您最好使用java.beans Introspector的反射工具,因为它会为您缓存所有反射内容。