繁体   English   中英

如何加快反射代码?

[英]How to speed up Reflection Code?

在我的应用程序中,我使用Apache的DBUtils类从MySQL数据库读取。 我编写了一个自定义BasicRowProcessor,它在数据对象的字段上使用批注来从数据库中读取列。 它在代码方面确实工作得很好,但是当我拉很多行时,性能却很慢。 例如,使用此代码,一个1500行x 35列的结果集将花费800ms,但是如果我使用的是标准JDBC代码,则只需要80ms。

问题-我可以怎样加快此代码的速度? 具体来说,我使用了很多反射和注释-是否缺少技巧来加快速度?

 @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;
 }

也许可以构建并缓存行映射逻辑,因此您不必每次都扫描字段,注释,结果集元数据和类型。

JDBC元数据访问特别慢。

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

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);
    }
}

不要比较类型的名称。 比较类型,以int.class,long.class等。

实际上,您不需要所有这些“ if”语句。 只需使用ResultSet.getObject()作为参数调用Field.set()。 正确的事情将在内部发生。 但是我没有说这会更快。

使用java.beans Introspector的反射功能会更好,因为它会为您缓存所有反射内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM