コンセプトノートのJAVA開発者としては見知らぬ人である必要があります。我々は通常サービス@、テスト、@上書き@などに、共通@Controllerのかなりの数を持っているとして、注釈の正しい使用は確かに私たちのために、アノテーションフレームワークのレベルを追加した後、例えば@Controllerに我々の開発を容易にすることができます多くを保存することは非常にコードの重複実際の開発の量を減らし、サーブレットレベルで共通のコードを記述する必要があります。
フレームワークが提供するこれらのアノテーションを使用することに加えて、我々はまた、我々のアプリケーションのための彼らの開発を容易にするための注釈をカスタマイズできるのカスタマイズ方法を見て、使用注釈、およびカスタムアノテーションを使用しての実用的な例を提供することができます。
コンセプトノート
JDK 1.5以降、Javaは、アノテーション(注釈)であるメタデータ(メタデータ)、のサポートを追加します。メモコードは、実際には、設定ファイルを置き換えるために使用される特殊なマーク、次のとおりです。ノートは技術を持った後、開発者が実行するためのクラスを伝えるためにどのように注釈を付けることができ、どのように設定ファイルを介して実行するクラスを伝えるための伝統的な方法。Java技術における代表的なアプリケーションの注釈があります:反射法によってクラスのノートの中に入るために、クラスを実行する方法を決定します。
注釈については、公式声明は次のとおりです。コメントは、メタデータのJavaコードに追加することができ、クラス、メソッド、変数、パラメータ、およびパッケージは、注釈を変更するために使用することができます。それはコードと直接影響を修飾れるノート。
注釈は、実際のデータ構造で、追加の情報は、私たちのクラス、プロパティ、メソッドに追加され、私たちは、ホスト論理判断にいくつかの拡張機能を使用することができます。
; 2、クラスファイルの段階にコンパイル; 3、実行時のフェーズ1、Javaソースファイルの段階:ノートのライフサイクルは三つの段階があります。
私たちは、実際の生産では、メタアノテーションを通じて当社のカスタム注釈のライフサイクルを構成することができ、最も広く使用されているので、我々は、カスタム注釈ライフサイクルが発効上で実行するように設定されます通常の状況下では、実行段階で注釈を使用することです。
元のメモ
上述したように、我々は、メタデータアノテーションを通じ、我々は同じ構成のメタアノテーションの注釈オブジェクトを使用することができ、かつ基本的な属性の役割ので、注釈ライフサイクルを構成することができます。メタアノテーションは、アノテーションの注釈の変形例です。
JDK 1.5は、注釈型の注釈に基づいて、4つの標準的な注釈で提供され、我々はメタアノテーション(メタアノテーション)を呼び出し、彼らは以下のとおりです。
ターゲット@、リテンション@、文書化@、@継承されています
私たちは、私たちは役割が導入されている1つのこれらの4元ノートずつ、そして、私たちのカスタム注釈型に注釈を付けるためにこれらの4元のノートを使用することができます。
図1は、ターゲット注釈:注釈の効果は:注釈が範囲を記載(例:修飾注釈が任意の場所で使用することができます)。それが注釈されていることをベース注釈を説明するためのターゲットアノテーションは目標範囲を変更することができる:注釈はパッケージ、型(クラス、インタフェース、列挙、注釈カテゴリ)、クラスのメンバ(メソッド、コンストラクタ、メンバ変数を変更するために使用することができ、使用@Targetアノテーションクラスをより明確に定義することができる列挙値)、メソッドの引数と、このようなループ変数とローカル変数(キャッチ・パラメータ)は、範囲のElementTypeで定義されたオブジェクトを修正するために使用することができるかを知ります列挙。
2、Reteniton注:注釈の効果は次のとおり説明保持時間アノテーション(すなわち:注釈は、そのクラスの変更に記載されているときに保持されます)。Reteniton注釈は、注釈クラスに使用され、それが他のクラスの後にメモを注釈されたものに限定され、RetentionPolicy列挙で定義された場合に、3つの戦略の合計まで保持することができます。
3、文書化注:注釈の役割は次のとおりです。あなたがその注釈情報を保持したい場合はjavadocツールを使用してヘルプファイルを生成するクラスを記述する場合。
4、継承注:注釈の役割がある:それはノートが継承されている修正された(クラスは、アノテーションを使用している場合@Inheritedは、それが自動的にノートのサブクラスを持つことになり、変更されました)。
私たちの最も頻繁にターゲットとReteniton。
例
比較的小さな注釈付きの基礎は、我々は実用的な生産の直接の例を開始しました。
製造においては、各格付けカテゴリーの属性項目のスコアのために、クラス遭遇したレーティング情報を記述するため。評価は、多くの項目(ゲッター/セッター省スペースすべてを無視する)は次のとおりです。
public class SysMark extends BaseEntity {
private String markReasons;
private String fj1ReasonSelf;
private Double fj1MarkSelf;
private String fj2ReasonSelf;
private Double fj2MarkSelf;
private String fj3ReasonSelf;
private Double fj3MarkSelf;
private String fj4ReasonSelf;
private Double fj4MarkSelf;
private String fj5ReasonSelf;
private Double fj5MarkSelf;
private String jf1ReasonSelf;
private Double jf1MarkSelf;
private String jf2ReasonSelf;
private Double jf2MarkSelf;
private String jf3ReasonSelf;
private Double jf3MarkSelf;
private String jf4ReasonSelf;
private Double jf4MarkSelf;
private String jf5ReasonSelf;
private Double jf5MarkSelf;
private String jf6ReasonSelf;
private Double jf6MarkSelf;
private String llxz1ReasonSelf;
private Double llxz1MarkSelf;
private String llxz2ReasonSelf;
private Double llxz2MarkSelf;
private String llxz3ReasonSelf;
private Double llxz3MarkSelf;
private String llxz4ReasonSelf;
private Double llxz4MarkSelf;
private String zygw1ReasonSelf;
private Double zygw1MarkSelf;
private String zygw2ReasonSelf;
private Double zygw2MarkSelf;
private String zygw3ReasonSelf;
private Double zygw3MarkSelf;
private String jsyw1ReasonSelf;
private Double jsyw1MarkSelf;
private String jsyw2ReasonSelf;
private Double jsyw2MarkSelf;
private String jsyw3ReasonSelf;
private Double jsyw3MarkSelf;
private String jsyw4ReasonSelf;
private Double jsyw4MarkSelf;
private String zgsx1ReasonSelf;
private Double zgsx1MarkSelf;
private String zgsx2ReasonSelf;
private Double zgsx2MarkSelf;
private String zgsx3ReasonSelf;
private Double zgsx3MarkSelf;
private String zgsx4ReasonSelf;private Double zgsx4MarkSelf;
private java.sql.Timestamp markTime;
private java.sql.Timestamp updateTime;
private String startTime;
private String endTime;
private String markId;
private Double markMark;
private String markMonth;
private String markYear;
private String markJiDu;
private long uid;
private String deptId;
}
目前接到的需求是,将评分项汇总,组成一个 “评分项1:得分1;评分项2:得分2...” 的字符串。其中每个评分项得分在实际语义中包含三种情况:加分项,减分项,否决项(总分直接判0)。
在通常情况下,我们一般便会通过 if - else 逐个判断每个属性是否有打分,判断该评分项的类型来决定得分是加分、减分还是直接判 0 。
但这样做会带来很多不方便,几十个 if 判断不说,万一我们要新增或减少一个评分项或者配错/漏配了一个评分项,我们需要那 if 的代码逐行的与类中的属性比对,非常的繁琐。这时候我们可以考虑自定义一个注解用于修饰这些属性,在定义属性时便为其附加 评分项名称 以及加减分/否决的属性,然后通过反射对所有属性统一进行处理。
我们来定义出这个注解:
/**
* @Author Nxy
* @Date 2020/2/15 13:17
* @Description 自定义评分原因注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.FIELD)
public @interface MarkReason {
//评分项目名称
public String reasonName();
//是否减分项
public boolean isSubtraction() default true;
//是否否决项
public boolean isFouJue() default false;
}
其中两个元注解的含义便是:@Retention(RetentionPolicy.RUNTIME):该注解在运行期生效;@Target(value = ElementType.FIELD):该注解作用于属性。
我们为注解定义了三个属性 resonName、isSubtraction、isFouJue,被 MarkReason 注解修饰的属性可以拥有这三个属性。
我们用该注解对上述评分类进行修饰后评分类变成这样:
public class SysMark extends BaseEntity { private String markReasons; private String fj1ReasonSelf; @MarkReason(reasonName = "责任区党员群众发生违法行为", isFouJue = true) private Double fj1MarkSelf; private String fj2ReasonSelf; @MarkReason(reasonName = "责任区党员群众发生撞“红线”及以上问题", isFouJue = true) private Double fj2MarkSelf; private String fj3ReasonSelf; @MarkReason(reasonName = "责任区党员群众参与群体上访、越级上访", isFouJue = true) private Double fj3MarkSelf; private String fj4ReasonSelf; @MarkReason(reasonName = "责任区发生打架斗殴等不良行为", isFouJue = true) private Double fj4MarkSelf; private String fj5ReasonSelf; @MarkReason(reasonName = "经研究其他否决项目的问题", isFouJue = true) private Double fj5MarkSelf; private String jf1ReasonSelf; @MarkReason(reasonName = "责任区党员群众发现安全重大隐患、防止安全事故、受到段级及以上表扬表彰或通报嘉奖", isSubtraction = false) private Double jf1MarkSelf; private String jf2ReasonSelf; @MarkReason(reasonName = "责任区党员群众参加技术比武获得名次", isSubtraction = false) private Double jf2MarkSelf; private String jf3ReasonSelf; @MarkReason(reasonName = "积极组织责任区党员群众 围绕安全、运输和技术难题立项攻关取得实效,受到总公司、 集团公司、段表彰", isSubtraction = false) private Double jf3MarkSelf; private String jf4ReasonSelf; @MarkReason(reasonName = "责任区党员群众完成急难险重任务成绩突出", isSubtraction = false) private Double jf4MarkSelf; private String jf5ReasonSelf; @MarkReason(reasonName = "责任区党员群众做好人好事、见义勇为事迹受到表彰奖励或媒体表扬", isSubtraction = false) private Double jf5MarkSelf; private String jf6ReasonSelf; @MarkReason(reasonName = "其他受到集团公司及以上表彰奖励", isSubtraction = false) private Double jf6MarkSelf; private String llxz1ReasonSelf; @MarkReason(reasonName = "责任区党员群众无故不参加上级组织的集体活动") private Double llxz1MarkSelf; private String llxz2ReasonSelf; @MarkReason(reasonName = "责任区内环境卫生差、备品摆放不整齐") private Double llxz2MarkSelf; private String llxz3ReasonSelf; @MarkReason(reasonName = "班组标准化验收不达标") private Double llxz3MarkSelf; private String llxz4ReasonSelf; @MarkReason(reasonName = "班组未完成生产任务,运输组织工作,旅客、货主等服务工作受到上级批评") private Double llxz4MarkSelf; private String zygw1ReasonSelf; @MarkReason(reasonName = "责任区党员群众发生迟到、早退") private Double zygw1MarkSelf; private String zygw2ReasonSelf; @MarkReason(reasonName = "责任区党员群众发生严重“两违”问题") private Double zygw2MarkSelf; private String zygw3ReasonSelf; @MarkReason(reasonName = "作业提醒不到位") private Double zygw3MarkSelf; private String jsyw1ReasonSelf; @MarkReason(reasonName = "不参加月度业务考试、模拟演练") private Double jsyw1MarkSelf; private String jsyw2ReasonSelf; @MarkReason(reasonName = "责任区党员群众月度考试或抽考成绩不达标") private Double jsyw2MarkSelf; private String jsyw3ReasonSelf; @MarkReason(reasonName = "应知应会考试、专业技能考核不达标") private Double jsyw3MarkSelf; private String jsyw4ReasonSelf; @MarkReason(reasonName = "责任区党员群众技术业务帮带效果不明显") private Double jsyw4MarkSelf; private String zgsx1ReasonSelf; @MarkReason(reasonName = "对责任区内职工思想动态不掌握、不熟悉、不了解,不能及时做思想工作") private Double zgsx1MarkSelf; private String zgsx2ReasonSelf; @MarkReason(reasonName = "未及时与发生“两违”问题的党员群众谈心谈") private Double zgsx2MarkSelf; private String zgsx3ReasonSelf; @MarkReason(reasonName = "未及时与困难党员群众谈心谈话") private Double zgsx3MarkSelf; private String zgsx4ReasonSelf; @MarkReason(reasonName = "未及时化解矛盾造成不良影响") private Double zgsx4MarkSelf; private java.sql.Timestamp markTime; private java.sql.Timestamp updateTime; private String startTime; private String endTime; private String markId; private Double markMark; private String markMonth; private String markYear; private String markJiDu; private long uid; private String deptId;
}
这样一来,在每个属性被定义时,它的语义便被一同写进了其注解中。我们通过反射获取每个属性的注解,对所有属性进行统一的处理:
/**
* @Author Nxy
* @Date 2020/2/15 14:14
* @Description 汇总加减分原因
*/
public static void setMarkReasons(BaseEntity markBean) throws IllegalAccessException, NoSuchFieldException {
Class beanClass = markBean.getClass();
Field[] fields = beanClass.getDeclaredFields();
if (fields == null || fields.length == 0) {
throw new RuntimeException(markBean + " has no field");
}
Field targetField = beanClass.getDeclaredField("markReasons");
StringBuilder reasonsSb = new StringBuilder();
//遍历属性
for (Field field : fields) {
//判断该属性是否被 MarkReason 注解修饰
if (field.isAnnotationPresent(MarkReason.class)) {
//允许私有属性访问
field.setAccessible(true);
String isSubtraction = "-";
MarkReason reasonAnno = field.getAnnotation(MarkReason.class);
Object markMark = field.get(markBean);
//判断该项是否已评分
if(markMark==null){
continue;
}
//判断是否是减分项
if (!reasonAnno.isSubtraction()) {
isSubtraction = "+";
}
String project="";
//判断是否否决项
if(reasonAnno.isFouJue()){
project = "-100";
}else {
project = isSubtraction + (double) markMark;
}
//拼装加减分原因
reasonsSb.append(reasonAnno.reasonName() + ":" + project + ";");
}
}
//汇总后将结果写入对象
targetField.setAccessible(true);
targetField.set(markBean, reasonsSb.toString());
}
通过上面的方法,我们只需要在定义一个新的评分项时将其用 @MarkReason 注解修饰即可,汇总评分原因的代码不需要做任何改变。而使用传统的 if 判断的方法时,新增/删除/改变一个评分项,相应的 if 节点的代码都需要做出对应的改变。并且相较 if 判断,该方法的代码量也减少了非常多。