Empfohlen (kostenlos): Java Basic Tutorial
Reflection ist eine fortgeschrittene Technik in Java, die in verschiedenen Open-Source-Projekten weit verbreitet ist . Beispielsweise nutzen Spring, Tomcat, Jetty und andere Projekte in großem Umfang Reflection.
Wenn wir als Java-Programmierer die Reflexion gut nutzen, können wir nicht nur unser technisches Niveau verbessern, sondern auch bessere Projekte entwickeln.
Obwohl viele Menschen von Reflexion gehört haben, wissen sie nicht, wo sie eingesetzt werden sollen.
Dann beginnen wir mit der eigentlichen Arbeit und konvertieren das Objekt mithilfe der Reflektion in die Datenstruktur von MongoDb. Nachdem Sie dieses Beispiel verstanden haben, werden Sie verstehen, wie Reflexion verwendet wird.
Im E-Commerce-System müssen einige Daten in MongoDb gespeichert werden, um die Abfrageleistung zu verbessern. Zuvor müssen wir jedoch zunächst die Daten in die MongoDb-Struktur konvertieren, also Java-Objekte in Dokumente umwandeln.
Wenn beispielsweise Bestellinformationen in MongoDb gespeichert werden sollen, muss das Bestellobjekt in ein Dokument umgewandelt werden.
Aber auf diese Weise muss jede Entitätsklasse eine 2Doc()-Methode entwickeln. Diese Methode hat keinen technischen Inhalt, sondern fügt lediglich verschiedene Felder in das Dokument ein. Und wenn es zu viele Felder gibt, schreiben Sie falschen Code, wenn Sie nicht aufpassen. Das können Sie spüren.
public class Order { private Long id; private Long userId; private String orderNo; private BigDecimal amount; private String createTime; private String updateTime; // 省略无数字段 // 转换方法:订单转doc public Document order2Doc(Order order) { Document doc = new Document(); doc.put("id", order.getId()); doc.put("userId", order.getUserId()); doc.put("orderNo", order.getOrderNo()); doc.put("amount", order.getAmount()); doc.put("createTime", order.getCreateTime()); doc.put("updateTime", order.getUpdateTime()); // 省略无数put... return doc; } }
Außerdem müssen wir die Daten von MongoDb abrufen und das Dokument wieder in ein Java-Objekt konvertieren.
public class Order { private Long id; private Long userId; private String orderNo; private BigDecimal amount; private String createTime; private String updateTime; // 省略无数字段 // 转换方法:doc转订单 public Order doc2Order(Document doc) { Order order = new Order(); order.setId((Long) doc.get("id")); order.setUserId((Long) doc.get("userId")); order.setOrderNo((String) doc.get("orderNo")); order.setAmount((BigDecimal) doc.get("amount")); order.setCreateTime((String) doc.get("createTime")); order.setUpdateTime((String) doc.get("updateTime")); // 省略无数set... return order; } }
Nur eine Auftragsklasse ist so problematisch, ganz zu schweigen davon, dass es mehr als eine solche Klasse gibt und das Projekt immer neue Anforderungen hat. Wenn ein Feld geändert wird, geraten Sie in große Schwierigkeiten und müssen möglicherweise durchgehen das gesamte Projekt.
Um Fehler zu reduzieren, müssen diese beiden Konvertierungsmethoden daher optimiert werden, und diese Optimierung nutzt zwei erweiterte Funktionen von Java: Reflektion und Generika. Um allen ein intuitiveres Verständnis zu ermöglichen, werde ich es in zwei Versionsiterationen unterteilen.
Die erste Version verwendet Reflektion, um die Konvertierungsmethode von Entitätsklassen zu vereinfachen.Die zweite Version verwendet Generika und Reflektion, um MongoDb-Toolklassen zu extrahieren.
Als nächstes iterieren wir Schritt für Schritt von Entitätsklassen
Beginnen wir mit der Konvertierung eines Java-Objekts in ein Dokument, wobei wir wiederum die Order-Klasse als Beispiel nehmen.
Zuerst erhalten wir alle Feldinformationen der Auftragsklasse durch Reflektion; dann verwenden wir eine Schleife, um diese Felder zu durchlaufen. Schließlich geben wir in der Schleife die Zugriffsrechte der Felder frei und fügen die Felder in das Dokument ein.
public class Order { // ...省略无数字段 public Document order2Doc(Order order) throws Exception { Document doc = new Document(); // 获取所有字段:通过 getClass() 方法获取 Class 对象,然后获取这个类所有字段 Field[] fields = order.getClass().getDeclaredFields(); for (Field field : fields) { // 开放字段操作权限 field.setAccessible(true); // 设置值 doc.put(field.getName(), field.get(order)); } return doc; } }
Sie können sehen, dass der Code nach der Reflexionstransformation viel einfacher ist. Unabhängig davon, wie viele Felder ein Objekt hat oder wie viele Put-Operationen geschrieben werden müssen, ist dies mit nur wenigen Codezeilen möglich. Das Konvertieren von Java-Objekten in MongoDb-Strukturen scheint weniger umständlich zu sein.
Nach dieser Idee transformieren wir die zweite Methode, das Dokument in ein Java-Objekt konvertieren.
public class Order { // ...省略无数字段 public Order doc2Order(Document doc) throws Exception { Order order = new Order(); for (String key : doc.keySet()) { // 获取字段 Field field = order.getClass().getDeclaredField(key); // 开放字段操作权限 field.setAccessible(true); // 设置值 field.set(order, doc.get(key)); } return order; } }
Zuerst verwenden wir eine Schleife, um das Dokument in der Schleife zu durchlaufen, verwenden Reflektion, um die entsprechenden Felder abzurufen, geben dann die Zugriffsrechte der Felder frei und setzen den Wert des Dokuments auf die Felder des Objekts.
Zu diesem Zeitpunkt haben wir Reflektion verwendet, um die Konvertierungsmethode der beiden Entitätsklassen zu vereinfachen, und die erste Version der Iteration ist im Wesentlichen abgeschlossen. Die verbleibende Arbeit besteht darin, jede Klasse zu kopieren, einzufügen und umzuformen.
Nach dieser Iteration gibt es jedoch immer noch viele unangemessene Stellen, obwohl viel Arbeit reduziert wurde.
Erstens gibt es immer noch viel doppelten Code. Jede Entitätsklasse verfügt über zwei Konvertierungsmethoden, die Kernlogik dieser beiden Methoden ist jedoch dieselbe, sodass sie nicht überall kopiert werden müssen.
Dann ist dies keine Funktion, die Entitätsklassen übernehmen sollten. Entitätsklassen sind nur für die vorübergehende Speicherung von Daten verantwortlich und nicht für Persistenzfunktionen. Wo Sie die Daten speichern und in welche Datenstruktur sie konvertiert werden sollen, hat nichts mit Entitätsklassen zu tun.
Mit anderen Worten, wir müssen eine zweite Iteration durchführen.
Verwenden Sie Generika und Reflektion, um MongoDb-Toolklassen zu extrahieren.
Wenn Sie Generics und Reflection kombinieren, können wir viel doppelten Code reduzieren.
Mal sehen, wie macht man die zweite Iteration?
Beginnen Sie mit der Konvertierung eines Java-Objekts in ein Dokument. Wir deklarieren zunächst eine generische Methode; dann erhalten wir durch Reflektion alle Feldinformationen der generischen Klasse und verwenden dann eine Schleife, um diese Felder zu durchlaufen und schließlich die Felder in das Dokument einzufügen.
public class MongoDbUtils { // 定义泛型方法: // 1. 在返回值前,声明泛型参数 <参数名>; // 2. 传入参数时,指定一个泛型参数 public static <T> Document obj2Doc(T obj) throws Exception { Document doc = new Document(); // 获取所有字段:通过 getClass() 方法获取 Class 对象,然后获取这个类所有字段 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { // 开放字段操作权限 field.setAccessible(true); // 设置值 doc.put(field.getName(), field.get(obj)); } return doc; } }
Nach dem Hinzufügen von Generika wurde der doppelte Code erheblich reduziert und Entitätsklassen müssen nicht mehr separat geschrieben werden
.2Doc()
方法了。在使用的时候,只要调用 MongoDbUtils.obj2Doc()
Der gleichen Idee folgend, transformieren wir weiterhin die zweite Methode, das Dokument in ein Java-Objekt konvertieren.
public class MongoDbUtils { // 定义泛型方法: // 1. 在返回值前,声明泛型参数 <参数名>; // 2. 传入参数必须是 Class,但这个 Class 是泛型参数,不限制类型 public static <T> T doc2Obj(Document doc, Class<T> clazz) throws Exception { // 实例化泛型对象 T obj = clazz.newInstance(); for (String key : doc.keySet()) { // 获取字段 Field field = clazz.getDeclaredField(key); // 开放字段操作权限 field.setAccessible(true); // 设置值 field.set(obj, doc.get(key)); } return obj; } }
首先,我们定义实例化一个泛型对象;然后,我们使用循环遍历 Document;最后,在循环中,使用反射获取相应的字段,把 Document 的值设置到泛型对象的字段里。
第二版的迭代就基本完成了。我们在第一版迭代的基础上,加入了泛型,得到了一个工具类 MongoDbUtils
,这个工具类得到结果和以前完全一样,你可以看下测试代码。
public static void main(String[] args) throws Exception { Order order = new Order(); order.setId(0L); order.setUserId(0L); order.setOrderNo("1"); order.setAmount(new BigDecimal("0")); order.setCreateTime("2"); order.setUpdateTime("3"); System.out.println("原始数据:" + order); Document document = MongoDbUtils.obj2Doc(order); System.out.println("转换doc数据:" + document); Order order1 = MongoDbUtils.doc2Obj(document, Order.class); System.out.println("转换java数据:" + order1); } 运行结果: 原始数据:Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3) 转换doc数据:Document{{id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3}} 转换java数据:Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3)
这样一来,我们就不用保留实体类上的转换方法了,剩下的工作就是删代码。
MongoDb 和 Java 对象的互相转换就完成了。我们做了两次迭代,第一次迭代利用了反射,把大量手动 set/get 操作给去掉了;第二次迭代在原来的基础上,加入了泛型的应用,又去掉了一堆重复代码。
Das obige ist der detaillierte Inhalt vonJava verwendet Reflektion, um Objekte in MongoDb-Strukturen zu konvertieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!