走自己的路

          路漫漫其修遠兮,吾將上下而求索

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            50 隨筆 :: 4 文章 :: 118 評論 :: 0 Trackbacks
          Asm是很好的ByteCode generator 和 ByteCode reader。Asm提供了ClassVisitor來訪問Class中的每個元素。當用ClassReader來讀取Class的字節碼時,每read一個元素,ASM會調用指定的ClassVisitor來訪問這個元素。這就是訪問者模式。利用這個特點,當ClassVisitor訪問Class的Annotation元素時,我們會把annotation的信息記錄下來。這樣就可以在將來使用這個Annotation。
          舉一個例子吧,我們用AnnotationFaker來標注一個Class,也就是Annotation的target是Type級別。當我們發現某個class是用AnnotationFaker標注的,我們就load這個class到jvm中,并初始化,否則免談。

          1.AnnotationFaker: annnotation用來標注需要初始化的class
           1package com.oocl.isdc.sha.frm.test.config;
           2
           3import java.lang.annotation.ElementType;
           4import java.lang.annotation.Retention;
           5import java.lang.annotation.RetentionPolicy;
           6import java.lang.annotation.Target;
           7
           8@Retention(RetentionPolicy.RUNTIME)
           9@Target({ElementType.TYPE})
          10public @interface AnnotationFaker {
          11}

          12

          2.ClassFaker: 被AnnotationFaker標注的class

          1package com.oocl.isdc.sha.frm.test.config;
          2
          3@AnnotationFaker
          4public class ClassFaker {
          5    public void hello() {
          6        System.out.println("hello world, load me success!");
          7    }

          8}

          9


          3.ClassVisitorFaker:ClassVisitor的一個實現,用來得到class上的Annotation

           1package com.oocl.isdc.sha.frm.test.config;
           2
           3import java.util.ArrayList;
           4import java.util.List;
           5
           6import org.objectweb.asm.AnnotationVisitor;
           7import org.objectweb.asm.Attribute;
           8import org.objectweb.asm.ClassVisitor;
           9import org.objectweb.asm.FieldVisitor;
          10import org.objectweb.asm.MethodVisitor;
          11import org.objectweb.asm.tree.AnnotationNode;
          12
          13public class ClassVisitorFaker implements ClassVisitor{
          14
          15    public List<AnnotationNode> visibleAnnotations;
          16
          17    public List<AnnotationNode> invisibleAnnotations;
          18    
          19    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
          20      
          21    }

          22
          23    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
          24        AnnotationNode an = new AnnotationNode(desc);
          25        if (visible) {
          26            if (visibleAnnotations == null{
          27                visibleAnnotations = new ArrayList<AnnotationNode> (1);
          28            }

          29            visibleAnnotations.add(an);
          30        }
           else {
          31            if (invisibleAnnotations == null{
          32                invisibleAnnotations = new ArrayList<AnnotationNode> (1);
          33            }

          34            invisibleAnnotations.add(an);
          35        }

          36        return an;
          37    }

          38
          39    public void visitAttribute(Attribute attr) {
          40    }

          41
          42    public void visitEnd() {
          43    }

          44
          45    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
          46        return null;
          47    }

          48
          49    public void visitInnerClass(String name, String outerName, String innerName, int access) {
          50    }

          51
          52    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
          53        return null;
          54    }

          55
          56    public void visitOuterClass(String owner, String name, String desc) {
          57    }

          58
          59    public void visitSource(String source, String debug) {
          60    }

          61
          62    public List<AnnotationNode> getVisibleAnnotations() {
          63        return visibleAnnotations;
          64    }

          65
          66    public List<AnnotationNode> getInvisibleAnnotations() {
          67        return invisibleAnnotations;
          68    }

          69}

          70


          4.ClassParser: main class, 分析classpath上的class,如果是用AnnotationFaker標注的class,我們就初始化它。

            1package com.oocl.isdc.sha.frm.test.config;
            2
            3import java.io.File;
            4import java.io.IOException;
            5import java.net.URISyntaxException;
            6import java.net.URL;
            7import java.net.URLClassLoader;
            8import java.net.URLDecoder;
            9import java.util.Enumeration;
           10import java.util.HashSet;
           11import java.util.Iterator;
           12import java.util.List;
           13import java.util.Set;
           14import java.util.zip.ZipEntry;
           15import java.util.zip.ZipException;
           16import java.util.zip.ZipFile;
           17
           18import org.objectweb.asm.ClassReader;
           19import org.objectweb.asm.Type;
           20import org.objectweb.asm.tree.AnnotationNode;
           21
           22public class ClassParser {
           23    @SuppressWarnings("unchecked")
           24    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException,
           25            IllegalAccessException, URISyntaxException {
           26        Set<String> result = new HashSet<String>();
           27
           28        if (getClassLoader() instanceof URLClassLoader) {
           29            URL[] urls = ((URLClassLoader) getClassLoader()).getURLs();
           30            for (URL u : urls) {
           31                File file = new File(u.toURI());
           32                if (file.isDirectory()) {
           33                    handleDirectory(result, file, null);
           34                }
           else if (file.getName().toLowerCase().endsWith(".jar")) {
           35                    handleArchive(result, file);
           36                }

           37            }

           38        }
          else{
           39            Enumeration<URL> urls = getClassLoader().getResources(".");
           40            while (urls.hasMoreElements()) {
           41                String urlPath = urls.nextElement().getFile();
           42                // System.out.println(urlPath);
           43                urlPath = URLDecoder.decode(urlPath, "UTF-8");
           44                if (urlPath.startsWith("file:")) {
           45                    urlPath = urlPath.substring(5);
           46                }

           47                if (urlPath.indexOf('!'> 0{
           48                    urlPath = urlPath.substring(0, urlPath.indexOf('!'));
           49                }

           50
           51                final File file = new File(urlPath);
           52                if (file.isDirectory()) {
           53                    handleDirectory(result, file, null);
           54                }

           55
           56            }

           57        }

           58
           59     
           60
           61        for (String clsRsName : result) {
           62            ClassVisitorFaker cv = new ClassVisitorFaker();
           63            ClassReader cr = new ClassReader(getClassLoader().getResourceAsStream(clsRsName));
           64            cr.accept(cv, 0);
           65            List<AnnotationNode> annotationsList = cv.getVisibleAnnotations();
           66            if (null != annotationsList) {
           67                for (Iterator<AnnotationNode> it = annotationsList.iterator(); it.hasNext();) {
           68                    AnnotationNode annotation = it.next();
           69                    Type t = Type.getType(annotation.desc);
           70                    if (AnnotationFaker.class.getName().equals(t.getClassName())) {
           71                        Class clazz = Class.forName(filenameToClassname(clsRsName));
           72                        ClassFaker faker = (ClassFaker) clazz.newInstance();
           73                        faker.hello();
           74                    }

           75                }

           76            }

           77
           78        }

           79
           80    }

           81
           82    private static void handleDirectory(final Set<String> result, final File file, final String path)
           83            throws ZipException, IOException {
           84        for (final File child : file.listFiles()) {
           85            final String newPath = path == null ? child.getName() : path + '/' + child.getName();
           86            if (child.isDirectory()) {
           87                handleDirectory(result, child, newPath);
           88            }
           else if (child.getName().toLowerCase().endsWith(".jar")) {
           89                handleArchive(result, child);
           90            }
           else {
           91                handleItem(result, newPath);
           92            }

           93        }

           94    }

           95
           96    private static void handleItem(final Set<String> result, final String name) {
           97        if (name.endsWith(".class")) {
           98            result.add(name);
           99        }

          100    }

          101
          102    private static void handleArchive(final Set<String> result, final File file) throws ZipException, IOException {
          103        final ZipFile zip = new ZipFile(file);
          104        final Enumeration<? extends ZipEntry> entries = zip.entries();
          105        while (entries.hasMoreElements()) {
          106            final ZipEntry entry = entries.nextElement();
          107            final String name = entry.getName();
          108            handleItem(result, name);
          109        }

          110    }

          111
          112    private static ClassLoader getClassLoader() {
          113        ClassLoader clsLoader = Thread.currentThread().getContextClassLoader();
          114        if (clsLoader == null{
          115            clsLoader = ClassLoader.getSystemClassLoader();
          116        }

          117        return clsLoader;
          118    }

          119
          120    public static String filenameToClassname(final String filename) {
          121        return filename.substring(0, filename.lastIndexOf(".class")).replace('/''.').replace('\\''.');
          122    }

          123
          124}

          125


          posted on 2008-06-11 17:38 叱咤紅人 閱讀(2943) 評論(0)  編輯  收藏 所屬分類: J2SE and JVM 、Other Java and J2EE frameworks
          主站蜘蛛池模板: 兴仁县| 桑植县| 凉城县| 安徽省| 尖扎县| 哈巴河县| 夏河县| 龙游县| 喀什市| 靖宇县| 镇坪县| 南充市| 海林市| 阿拉善右旗| 灵山县| 龙门县| 天镇县| 南岸区| 肥乡县| 通江县| 清河县| 陆河县| 玛多县| 辽阳市| 星子县| 大竹县| 永德县| 区。| 沙河市| 陈巴尔虎旗| 镇沅| 大埔区| 左云县| 大兴区| 遂昌县| 内丘县| 恭城| 万宁市| 兴宁市| 黑龙江省| 沙河市|