JAVA の初期の頃、Web フレームワークは Struts や Spring などのインターフェイスを管理するために XML ファイルを使用していました。 そのコンポーネントは基本的に XML ファイルで定義され、システムの起動時に XML ファイルを通じてロードされます。 このモードで開発されたシステムはファイルが肥大化しており、保守と管理が非常に困難です。
その後、Java は Java のリフレクション メカニズムと組み合わせたアノテーションを導入しました。 これはインターフェイスを管理するための非常に便利な方法を提供し、構築されたシステムは非常にシンプルでエレガントです。 その具体的な応用例を見てみましょう。
まず、メソッドに作用するアノテーションを定義します。
package webfunc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestFunction {
String action();
boolean cached() default false;
boolean isSynchronize() default false;
String explain() default "Request function";
}
// @RequestFunction (action = "personVerify")
// public ResponseData personVerifyMethod(WebSystemContext context) {
//..............
// }
このアノテーションの ElementType.METHOD 属性は、このアノテーションがメソッドに適用されることを表します。 システムのニーズに応じて、キャッシュ、非同期操作などの他の関数を定義することもできます。 注釈を定義した後、それを上記のビジネス コードと同様に使用して、システムがどのように注釈をロードするかを確認できます。
続行する前に簡単に説明しますが、アノテーションの内容は次のとおりです: @RequestFunction (action = “personVerify”)。
実行する必要があるコードは次のとおりです: public ResponseData personVerifyMethod(WebSystemContext context)。
これには、リクエスト命令とメソッドとの対応関係が必要であり、リクエスト命令を通じて対応するメソッドが実行される。
実際にメソッド呼び出しを実行するクラスを定義します。 呼び出す必要があるクラスとメソッドがあります。メソッドを呼び出すだけです。
package webfunc;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InvokedFunction {
public Method method;
public Class<?> clazz;
public boolean single;
public boolean cached;
public boolean voided;
public Object execute(WebSystemContext context) {
Object refer = null;
try {
if (this.single != true) {
refer = clazz.newInstance();
}
Object[] args = new Object[]{context};
Object result = method.invoke(refer, args);
return voided == true ? null : result;
} catch (InstantiationException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getTargetException());
}
}
}
このクラスはJavaのリフレクション機構を利用しており、パラメータと戻り値に従って実行する必要のあるメソッドを実行することを目的としています。 これらの内容の定義は、プリロードされたクラス インスタンス、メソッド名、およびその他の属性です。
命令クラスを定義して、リクエスト命令と呼び出しメソッドの関係を管理します。
package webfunc;
import java.util.HashMap;
import java.util.Map;
public class InvokeCommand {
Map<String, InvokedFunction> funcMap;
public InvokeCommand() {
funcMap = new HashMap<String, InvokedFunction>();
}
public boolean hasFunction(String func) {
return funcMap.containsKey(func);
}
public InvokedFunction getFunction(String func) {
return InvokeCommand.this.funcMap.get(func);
}
public void put(String func, InvokedFunction invFunc) {
this.funcMap.put(func, invFunc);
}
}
このクラスでは、リクエスト命令と呼び出されるオブジェクトの間の関係を管理するマップを維持します。 たとえば、命令が personVerify の場合、対応する呼び出されるメソッドは public ResponseData personVerifyMethod(WebSystemContext context) です。
システムの起動時にこれらのアノテーションとメソッドをロードしたいと考えています。
package webfunc;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
public class ServiceContext {
public static Map<String, InvokeCommand> cmmdMap;
private static ServiceContext context;
private ServiceContext() {
cmmdMap = new HashMap<String, InvokeCommand>();
try{
//...preload the Commands from xml file...
//the business class
String classStr = "com.test.example.Business.UserAction";
//Request Command
String commandStr = "personVerify";
this.parseWebModule(Class.forName(classStr), commandStr);
}catch(Exception e){
e.printStackTrace();
}
}
public static ServiceContext getContext() {
if (context == null) {
context = new ServiceContext();
}
return ServiceContext.context;
}
public boolean hasCommand(String cmmd) {
return cmmdMap.containsKey(cmmd);
}
public InvokeCommand getCommand(String cmmd) {
return this.cmmdMap.get(cmmd);
}
public void parseWebModule(Class<?> clz, String code) {
Class<RequestFunction> antClass = RequestFunction.class;
for (Method method : clz.getMethods()) {
int modify = method.getModifiers();
if (Modifier.isPublic(modify)) {
RequestFunction webfunc = null;
if (method.isAnnotationPresent(antClass)) {
webfunc = method.getAnnotation(antClass);
if (code.equals(webfunc.action())) {
InvokeCommand proxy = null;
if (!cmmdMap.containsKey(code)) {
proxy = new InvokeCommand();
cmmdMap.put(code, proxy);
}
InvokedFunction webmethod = null;
webmethod = new InvokedFunction();
webmethod.clazz = clz;
webmethod.method = method;
webmethod.cached = webfunc.cached();
webmethod.single = Modifier.isStatic(modify);
Class<?> returnType = method.getReturnType();
webmethod.voided = returnType.equals(Void.class);
proxy = cmmdMap.get(code);
proxy.put(code, webmethod);
}
}
}
}
}
}
このクラスでは、設定ファイルを通じて業務実行クラスと業務実行メソッドを読み込みました。 あらかじめメモリにロードしておくことで、リクエストが到着した際に、そのリクエストコマンドが正当であるかどうかを判断することができます。
正当な場合は、対応するメソッドを呼び出すことができます。 その後、クライアントに応答を返します。ここでも JAVA のリフレクション メカニズムが使用されます。
ここでのビジネス実行クラスと呼び出しコマンドはすべて、ファイル内で均一に構成およびロードされる必要があります。
現在、ほとんどのフレームワークでモードが変更されており、これにより構成ファイルも肥大化します。 現在、ほとんどのフレームワークはアノテーションを取得し、Java のリフレクション メカニズムを使用してそのコンテンツを解析します。
以下は、アノテーションとリフレクションのメカニズムが Java フレームワークの開発にどのように役立つかを示す単なる例です。
この一連のものは、Web フレームワークだけでなく、C/S 構造のインターフェース プラットフォームでも使用でき、非常に実用的です。