Java注解应用,自定义注解映射实现方案说明.

插件结构如图:

注册模块定义了三个: 用于实体与表映射的注解, 用于属性到表字段的映射, 用于映射时过滤掉的注解.

1. 用于实体与表映射的注解

package com.dobby.plugins.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**

  • User: 苏若年
  • Date: 14-10-9
  • Time: 下午 21:12
  • Description:
    */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GeneratorTable {

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">标注映射时的表名</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> String name() <span style="color: rgba(0, 0, 255, 1)">default</span> ""<span style="color: rgba(0, 0, 0, 1)">;

}

2. 用于属性与字段映射的注解

package com.dobby.plugins.annotation;

import java.lang.annotation.*;

/**

  • User: 苏若年

  • Date: 14-10-9

  • Time: 下午 21:31

  • Description:
    */
    @Target({ElementType.METHOD,ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface GeneratorField {

    /**

    • 是否为主键
    • @return
      */
      boolean primaryKey() default false;

    /**

    • 映射的字段名
    • @return
      */
      public String name() default "";
      }

3. 用于废弃字段过滤的注解

package com.dobby.plugins.annotation;

import java.lang.annotation.*;

/**

  • User: 苏若年
  • Date: 14-10-9
  • Time: 下午 21:15
  • Description:
    */
    @Target({ElementType.METHOD,ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface AbolishedField {
    //标注映射时排除的字段
    }

注解定义完成后, 我们需要在扫描到的实体中根据注解映射规则进行扫描时自动封装

自动封装的核心业务逻辑如下

    /**
     * 根据对象构造, 表映射
     * @param object
     *                 实体对象
     * @return
     *                 实体对象到字段表的映射, 基于注解处理
     */
    public static EntityTable constructEntityTableWithObject(Object object){
        EntityTable entityTable = null;
        try{
            if(null == object){return null;}
        ConcurrentMap</span>&lt;String,String&gt; entityToTable = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap&lt;String, String&gt;<span style="color: rgba(0, 0, 0, 1)">();
        </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> isGeneratorTable = object.getClass().isAnnotationPresent(GeneratorTable.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
        System.out.println(object.getClass().getSimpleName());
        </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(isGeneratorTable){
            GeneratorTable generatorTable </span>= object.getClass().getAnnotation(GeneratorTable.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(StringUtils.isBlank(generatorTable.name())){
                entityToTable.put(object.getClass().getSimpleName(),firstLower(object.getClass().getSimpleName()));
            }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
                entityToTable.put(object.getClass().getSimpleName(),generatorTable.name());
            }
        }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
            entityToTable.put(object.getClass().getSimpleName(),firstLower(object.getClass().getSimpleName()));
        }
        Field[] fields </span>=<span style="color: rgba(0, 0, 0, 1)"> object.getClass().getDeclaredFields();
        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> fields){
            entityTable </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> EntityTable();
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">主键组</span>
            ConcurrentMap&lt;String,String&gt; propertyToKey = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap&lt;String,String&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">字段组</span>
            ConcurrentMap&lt;String,String&gt; propertyToColumn = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap&lt;String, String&gt;<span style="color: rgba(0, 0, 0, 1)">();
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">主键到集合类型映射</span>
            ConcurrentMap&lt;String,Object&gt; propertyPKeyType = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap&lt;String,Object&gt;<span style="color: rgba(0, 0, 0, 1)">();

            </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; fields.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断是否剔除</span>
                <span style="color: rgba(0, 0, 255, 1)">boolean</span> isAbolishedField = fields[i].isAnnotationPresent(AbolishedField.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(isAbolishedField){
                    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">跳过该字段的提取</span>
                    <span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
                }
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断是否是主键</span>
                <span style="color: rgba(0, 0, 255, 1)">boolean</span> isGeneratorField = fields[i].isAnnotationPresent(GeneratorField.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(isGeneratorField){
                    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取注解中的文字说明</span>
                    GeneratorField generatorField =  fields[i].getAnnotation(GeneratorField.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
                    </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> primaryKey =<span style="color: rgba(0, 0, 0, 1)"> generatorField.primaryKey();
                    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(primaryKey){
                        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加到主键集合</span>

propertyPKeyType.put(fields[i].getName(),fields[i].getType().getName());
propertyToKey.put(fields[i].getName(),generatorField.name());
}
else{
if(StringUtils.isBlank(generatorField.name())){
propertyToColumn.put(fields[i].getName(),fields[i].getName());
}
else{
propertyToColumn.put(fields[i].getName(),generatorField.name());
}
}
continue;
}
propertyToColumn.put(fields[i].getName(), fields[i].getName());
}
entityTable.setPropertyPKeyType(propertyPKeyType);
entityTable.setPropertyToPKey(propertyToKey);
entityTable.setPropertyToColumn(propertyToColumn);
}
entityTable.setEntityToTable(entityToTable);
}
catch (Exception e){
e.printStackTrace();
}
return entityTable;
}

EntityTable 时实体与表结构映射的一个简易对象.

如下, 我们定义的实体

package com.dobby.code.make.model;

import com.dobby.plugins.annotation.AbolishedField;
import com.dobby.plugins.annotation.GeneratorField;
import com.dobby.plugins.annotation.GeneratorTable;

import java.io.Serializable;

/**

  • Created by 苏若年 on 2014/11/26.
    */
    //映射表别名
    @GeneratorTable(name = "tb_member")
    public class Member implements Serializable {

    //映射该字段, 并且为主键, 自定义字段别名
    @GeneratorField(primaryKey = true, name = "m_Id")
    private Integer id;

    @GeneratorField(name = "member_name")
    private String memberName;

    //映射时不映射该字段
    @AbolishedField
    private String address;

    //不使用注解, 默认为使用属性名进行映射
    private String zipCode;

    //getter and setter

}

 查看实体映射过程

 EntityTable entityTable = BeanUtils.constructEntityTableWithPath("com.dobby.code.make.model.Member");
 System.out.println("主键映射" + entityTable.getPropertyToPKey());
 System.out.println("字段映射" + entityTable.getPropertyToColumn());
 System.out.println("主键集合" + entityTable.getPropertyPKeyType());
 System.out.println("表名映射" + entityTable.getEntityToTable());

通过注解映射后的结果如下:

主键映射 {id=m_Id}
字段映射 {zipCode=zipCode, memberName=member_name}
主键集合 {id=java.lang.Integer}
表名映射 {Member=tb_member}

因为使用了注解映射过滤, 所以 address 字段映射时被排除.

转载请注明出处:[http://www.cnblogs.com/dennisit/p/4125103.html]