Java 如何加速反射代码?

Java 如何加速反射代码?,java,performance,reflection,Java,Performance,Reflection,在我的应用程序中,我使用Apache的DBUtils类从MySQL数据库中读取数据。我编写了一个定制的BasicRowProcessor,它使用数据对象字段上的注释从数据库中读取列。它在代码方面工作得非常好,但是当我拉很多行时,性能相当慢。例如,使用此代码,1500行x35列的结果集需要800毫秒,但如果使用标准JDBC代码,则只需要80毫秒 问题-我可以做些什么来加速此代码?具体地说,我使用了大量的反射和注释——是否有我遗漏的加快速度的技巧 @Override public <T

在我的应用程序中,我使用Apache的DBUtils类从MySQL数据库中读取数据。我编写了一个定制的BasicRowProcessor,它使用数据对象字段上的注释从数据库中读取列。它在代码方面工作得非常好,但是当我拉很多行时,性能相当慢。例如,使用此代码,1500行x35列的结果集需要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;
 }
@覆盖
公共T toBean(结果集rs,类类型)引发SQLException
{
T data=type.newInstance();
字段[]f=type.getFields();

对于(int i=0;i不比较类型的名称。将类型与int.class、long.class等进行比较

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


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

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

JDBC元数据访问特别慢

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

public BasicRowProcessor GetReflectVerowMapper(结果集rs,字符串结果集键,类类型){
字符串键=resultSetKey+“-”+类型;
BasicRowProcessor result=rrmCache.get(键);
如果(结果!=null){
结果=BuildReflectVerowMapper(rs、resultSetKey、类型);
rrmCache.put(键、结果);
}
返回结果;
}
公共BuiltRowProcessor BuildReflectVerowMapper(结果集rs,字符串结果集键,类类型){
}
然后

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);
    }
}
公共类BuiltRowProcessor扩展了基本处理器{
受保护的字段映射[]映射;
@凌驾
公共T toBean(结果集rs,类类型)引发SQLException{
T data=type.newInstance();
for(字段映射字段:映射){
字段.映射字段(rs,数据);
}
返回数据;
}
}
抽象公共类字段映射{
保护地;
受保护的int列索引;
//建造师。。
抽象公共void映射字段(ResultSet rs,Object target)抛出SQLException;
受保护的void writeField(对象目标、对象值){
试一试{
field.setValue(target,value);//或任何API。
}捕获(异常x){
抛出新的RuntimeException(“错误写入字段:”+字段,x);
}
}
}
公共IntMapping扩展了FieldMapping{
//建造师。。
公共void映射字段(结果集rs,对象目标)引发SQLException{
int值=rs.getInt(columnIndex);
writeField(目标、值);
}
}

如果你的代码有效,你应该改为发布到。提示一:不要使用反射。你为什么要这样做而不是使用现有的JPA实现?@antoh,但它没有,它太慢了。而且CR已经死了(或者还没有出生),你不能期望在那里得到任何答案。@maaartinus对我来说,太慢是一个有效的代码,但没有我想要的那么快,根据它的页面,这就是CR的用途。而且,如果没有人使用它,它永远不会起飞:)难道
Class
Method
不也做内部缓存吗?@SotiriosDelimanolis我想是的。在某些情况下,自己的缓存会阻止一些JIT优化(我可能是错的)。在函数上运行一些度量,是否将类型与int.Class进行比较或将type.getShortName()与“int”进行比较并不重要。这些都同样快。真正慢的代码在注释检索函数isAnnotationPresent()和getAnnotation()中。75%的函数时间在这两行代码中。
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);
    }
}