[JAVA] Erstellen Sie ein Reflexionsprogramm ①

Einführung

Manchmal mache ich eine einzelne Einheit mit JUnit, aber es ist mühsam, einen Prozess zu erstellen, um jedes Mal eine private Methode auszuführen. Notieren Sie sich dies hier. Es ist nicht auf das Testen beschränkt, sondern wird wahrscheinlich nur für Testcode verwendet.

Methode zum Ausführen einer privaten Methode

Params.java


package com.example.demo.util;

import java.lang.reflect.Method;

public class ReflectionUtil {

	/**
	 *Führen Sie eine private Methode aus (kein Argument).
	 * @Instanz, die die param obj-Methode ausführt
	 * @param methodName Methodenname
	 * @param params Argument
	 * @Rückgabewert der Rückgabemethode
	 * @throws Exception
	 */
	public static Object invokePrivate(Object obj, String methodName) throws Exception {
		Class<?> clazz = obj.getClass();
		Method method = clazz.getDeclaredMethod(methodName);
		method.setAccessible(true);
		return method.invoke(obj);
	}

	/**
	 *Führen Sie eine private Methode aus (mit Argumenten).
	 * @Instanz, die die param obj-Methode ausführt
	 * @param methodName Methodenname
	 * @param params Argument
	 * @Rückgabewert der Rückgabemethode
	 * @throws Exception
	 */
	public static Object invokePrivate(Object obj, String methodName, Params params) throws Exception {
		if(params == null ){
			throw new NullPointerException("params is required");
		}
		Class<?> clazz = obj.getClass();
		Method method = clazz.getDeclaredMethod(methodName, params.getTypes());
		method.setAccessible(true);
		return method.invoke(obj, params.getArgs());
	}
}

GetDeclaredMethod ruft das Methodenobjekt übrigens aus dem Objekt java.lang.Class ab, sodass Sie es für statische Methoden nicht instanziieren müssen. Sie können die Klasse also direkt an das erste Argument von invokePrivate übergeben und getDeclaredMethod ausführen.

Klasse, die Argumente zusammenfasst

Eine Klasse zum Sammeln der Argumente, die zum Ausführen einer privaten Methode mit den obigen Argumenten erforderlich sind.

Params.java


package com.example.demo.util;

import java.util.ArrayList;
import java.util.List;

import lombok.Data;

public class Params {

	private List<Param> paramList;

	public Params() {
		paramList = new ArrayList<>();
	}

	/**
	 *Konstruktor, der Argumente gleichzeitig mit der Initialisierung angibt.
	 * @param type
	 * @param arg
	 */
	public <T> Params(Class<T> type, T arg) {
		this();
		add(type, arg);
	}

	/**
	 *Legen Sie Argumente und ihre Typen fest.
	 * @param type
	 * @param arg
	 */
	public <T> void add(Class<T> type, T arg) {
		paramList.add(new Param(type, arg));
	}

	/**
	 *Gibt den festgelegten Argumenttyp als Array zurück.
	 * @return
	 */
	public Class<?>[] getTypes() {
		Class<?>[] types = new Class[paramList.size()];
		for (int i = 0; i < paramList.size(); i++) {
			types[i] = paramList.get(i).getType();
		}
		return types;
	}

	/**
	 *Gibt das set-Argument als Array zurück.
	 * @return
	 */
	public Object[] getArgs() {
		Object[] args = new Object[paramList.size()];
		for (int i = 0; i < paramList.size(); i++) {
			args[i] = paramList.get(i).getArg();
		}
		return args;
	}

	/**
	 *Klasse, die ein Argument darstellt.<br />
	 *Es hat ein Argumentobjekt und seinen Typ als Attribute.
	 *
	 */
	@Data
	private class Param {
		private Class<?> type;
		private Object arg;

		<T> Param(Class<T> type, T arg) {
			this.type = type;
			this.arg = arg;
		}
	}
}

Versuche zu rennen

--Privatmethode zum Testen

Private Methode getestet werden

Bereiten Sie eine private Methode mit einem geeigneten Argument vor.

Test.java


	private String doSomthing(int i, Long l, String str){
		System.out.println(Integer.toString(i));
		System.out.println(l.toString());
		System.out.println(str);
		return "Erledigt!";
	}

Testfall

UtilTest.java


	@Test
	public void test1() {
		AService test = new AService();	
		//Versuchen Sie, das erste Argument im Konstruktor anzugeben
		Params params = new Params(int.class, 1);
		//Dann mit add hinzufügen
		params.add(Long.class, 20L);
		params.add(String.class, "Drittes Argument");
		try {
			//Lauf
			String ret = (String) ReflectionUtil.invokePrivate(test, "doSomthing", params);
			System.out.println(ret);
		} catch (Exception e) {
			e.printStackTrace();
			fail();
		}
	}

Bei der tatsächlichen Verwendung ist invokePrivate leichter zu erkennen, wenn es statisch importiert wird.

Ausführungsergebnis

Ausführungsergebnis


1
20
Drittes Argument
Erledigt!

Apropos,

UtilTest.java


	/**
	 *Wenn null anstelle von params angegeben wird.
	 */
	@Test
	public void testParamsNull() {
		AServices = new AService();
		try {
			ReflectionUtil.invokePrivate(s, TARGET_METHOD, null);
			fail();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 *Wenn die in params festgelegten Argumente nicht übereinstimmen.
	 */
	@Test
	public void testParamsInvalid() {
		AService s = new AService();
		Params params = new Params(int.class, 1);
		params.add(Long.class, 20L);
		try {
			ReflectionUtil.invokePrivate(s, TARGET_METHOD, params);
			fail();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

Ausführungsergebnis testParamsNull()


java.lang.NullPointerException: params is required
	at com.example.demo.util.ReflectionUtil.invokePrivate(ReflectionUtil.java:32)
	at com.example.demo.UtilTest.test1(UtilTest.java:33)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	:

Ausführungsergebnis testParamsInvalid()


java.lang.NoSuchMethodException: com.example.demo.service.AService.doSomthing(int, java.lang.Long)
	at java.lang.Class.getDeclaredMethod(Class.java:2122)
	at com.example.demo.util.ReflectionUtil.invokePrivate(ReflectionUtil.java:35)
	at com.example.demo.UtilTest.test1(UtilTest.java:33)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	:

das ist alles.

Recommended Posts

Erstellen Sie ein Reflexionsprogramm ②
Erstellen Sie ein Reflexionsprogramm ③
Erstellen Sie ein Reflexionsprogramm ①
[Java] Mach es konstant
Machen Sie einen Diamanten mit Java
Machen Sie mit Ruby2D ein Labyrinth
Mach eine Sprache! (Einen einfachen Taschenrechner machen ②)
Versuchen Sie, einen einfachen Rückruf zu tätigen
Erstellen Sie mit JavaFX ein Diashow-Tool
So erstellen Sie einen Java-Container
So erstellen Sie einen JDBC-Treiber
Priority Queue max Machen Sie es zu einer Warteschlange
Mach eine Sprache! (Java CC-Umgebungskonstruktion)
Machen Sie eine Müllabfuhr mit line-bot-sdk-java
Erstellen Sie eine Listenkarte mit LazyMap
Ein Murmeln über die Utility-Klasse
So erstellen Sie einen Begrüßungsbildschirm
So erstellen Sie ein Jenkins-Plug-In
Wie erstelle ich ein Maven-Projekt?
Machen Sie einen SOAP-Aufruf in C #
Versuchen Sie, einen Iterator zu erstellen, der einen Blick darauf werfen kann
So erstellen Sie ein Java-Array
Machen Sie ein Tippspiel mit Ruby
So erstellen Sie eine Java-Kalenderzusammenfassung
Notieren Sie sich die Ruby-Schlüsselwortargumente
Machen wir eine Weihnachtskarte mit Verarbeitung!
Erstellen Sie mit Sinatra eine Familien-ToDo-Liste
Wie erstelle ich einen Discord Bot (Java)
Erstellen Sie mit Sinatra eine Familien-ToDo-Liste
Erstellen Sie trotzdem eine Anmeldefunktion mit Rails
[Docker] [Nginx] Erstellen Sie mit Nginx eine einfache ALB
[Java] Erstellen wir eine DB-Zugriffsbibliothek!