Java 自定义注解解析器

通用的注解解析器,当前只分析了Field上的注解,其他地方的注解解析原理相同。

直接上代码

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * Created by zl on 14/12/8.
 */
public class KitAnnotation {
    private static Map<String,List<Method>> annotationMethods=new HashMap<>();
    private static Map<String,Class<? extends Annotation>> classedLoaders=new HashMap<>();
    public static void addAnnotation(Class<? extends  Annotation> cls){
        if(!annotationMethods.containsKey(cls.getName())){
            List<Method> list=new ArrayList<>();
            list.addAll(Arrays.asList(cls.getDeclaredMethods()));
            annotationMethods.put(cls.getName(),list);
        }
    }
    private static  Map<Class,AnnotationProcessor> annotationCache =new HashMap<>();

    private static <T> AnnotationProcessor<T> getCache(T t){
        Class<T> cls= (Class<T>) t.getClass();
        AnnotationProcessor<T> cache= annotationCache.get(cls);
        if(cache == null){
            cache=new AnnotationProcessor(cls);
            annotationCache.put(cls, cache);
        }
        return cache;
    }


    public static <T> void process(T t){
        getCache(t).setValue(t);
    }


   static class AnnotationProcessor<T> {

        private  Map<String,List<Field>> fieldAnnotations=new HashMap<>();

        public AnnotationProcessor(Class<T> cls){
            analysis(cls);
        }

        public  void analysis(Class<T> cls){
            Field[] declaredFields = cls.getDeclaredFields();
            Annotation[] ans;
            String k;
            for (Field field:declaredFields){
                field.setAccessible(true);
                ans=field.getDeclaredAnnotations();
                if(ans != null){
                    for (Annotation a:ans){
                        k=a.annotationType().getName();
                        List<Field> fields = fieldAnnotations.get(k);
                        if(fields == null){
                            fields=new ArrayList<>();
                            fieldAnnotations.put(k,fields);
                        }
                        fields.add(field);
                    }
                }
            }
        }

        public  void setValue(T t){
            Set<Map.Entry<String, List<Field>>> entries = fieldAnnotations.entrySet();
            Class<? extends Annotation> cls;
            for(Map.Entry<String, List<Field>> entry:entries){
                try {

                    List<Method> list = annotationMethods.get(entry.getKey());
                    if(list != null && !list.isEmpty()) {
                        cls=classedLoaders.get(entry.getKey());
                        if(cls == null){
                            cls= (Class<? extends Annotation>) Class.forName(entry.getKey());
                            classedLoaders.put(entry.getKey(),cls);
                        }
                        for (Method method : list) {
                            for (Field field : entry.getValue()) {
                                field.set(t, method.invoke(field.getAnnotation(cls)));
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}


用法

//先加入分析
KitAnnotation.addAnnotation(CustomerAnnotation.class); //自定义的注解类
//然后就可以解析属性上的注解了
KitAnnotation.process(new UserBean());


这个类只是简单的实现了用注解设置属性上的值,其他的特性未实现!


对比常规的实现(不要喷我,这个是最基本的实现方法)

public static void parseAnnotation(UserBean userBean){
        //性能瓶颈在下面这一行,非常耗时!!定义在方法外面的话就和上面写的一样了~~
        Field[] declaredFields = UserBean.class.getDeclaredFields();  
        for (Field field:declaredFields){
            try {
            field.setAccessible(true);
            DefBeanId anId = field.getAnnotation(DefBeanId.class);
            if(anId != null){
                field.set(userBean,anId.id()); //anId.id()是自定义注解的方法                
            }
            DefColum anColum = field.getAnnotation(DefColum.class);
            if(anColum != null){
                field.set(userBean,anColum.name());
            }
            }catch (Exception e){
            }
        }   
}
public static void main(String[] args){
    UserBean userBean=new UserBean();
    int count=100000;
    long s=System.currentTimeMillis();
    for( int i=0;i<count;i++){
        KitAnnotation.parseAnnotation(userBean);
    }
    System.out.println(System.currentTimeMillis()-s);
    System.out.println("---------");
    
    s=System.currentTimeMillis();
    KitAnnotation.addAnnotation(DefBeanId.class);
    KitAnnotation.addAnnotation(DefColum.class);
    for( int i=0;i<count;i++){
        KitAnnotation.process(userBean);
    }
    System.out.println(System.currentTimeMillis()-s);

}

输出结果

4458

---------

125

在十万次测试中速度比上面的常规方法快30倍左右,当然我这样测试的不是很准,但至少性能上应该会用一些提升吧。

这个类只是为了方便的解析属性上的注解,把如上面常规实现改一下,就没什么性能优势了,但好处在于不用把代码写死,

简化了一些相同的代码。



转载于:https://my.oschina.net/u/866379/blog/353887

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值