给某一个类新增加属性

0 0

java动态的给对象附加属性。20

假如现在有一个属性配置文件,我需要去读取里面的属性并且是产生一个对象获取它,比如有一个xxx.txt文件:

a = 1

b = "hello"

 

我现在调用如下语句:

neatpropertybundle property  = new neatpropertybundleproperty("xxx.txt");

 

调用Systen.out.println(property.a),System.out.println(property.b);

代理的话如何实现,或者实现就行。


问题补充:<div class="quote_title">duanhengtao03 写道</div><div class="quote_div">只是读出他的value吗?</div> <br />是的,一定要通过调用属性的方式。。

问题补充:<div class="quote_title">jbutton 写道</div><div class="quote_div">通过程序修改 .class 文件!<strong>&lt;&lt;希望你参考下&gt;&gt;</strong> <br />下面这个是用 ASM 工具为 Student 类添加一个 public String 类型的 address 属性: <br /><strong>1,需要添加属性的原始类:Student.java</strong> <br /><pre name="code" class="java"> 
public class Student { 
    private int age; 
    private String name; 
    public int getAge() { 
        return age; 
    } 
    public void setAge(int age) { 
        this.age = age; 
    } 
    public String getName() { 
        return name; 
    } 
    public void setName(String name) { 
        this.name = name; 
    }    

</pre> <br /><strong>2,添加属性的适配器:AddFieldAdapter.java</strong> <br /><pre name="code" class="java"> 
import org.objectweb.asm.ClassAdapter; 
import org.objectweb.asm.ClassVisitor; 
import org.objectweb.asm.FieldVisitor; 

public class AddFieldAdapter extends ClassAdapter { 
    private int accessModifier; 
    private String name; 
    private String desc; 
    private boolean isFieldPresent; 

    public AddFieldAdapter(ClassVisitor cv, int accessModifier, String name, String desc) { 
        super(cv); 
        this.accessModifier = accessModifier; 
        this.name = name; 
        this.desc = desc; 
    } 

    @Override 
    public FieldVisitor visitField(int access, String name, String desc, 
            String signature, Object value) { 
        if (name.equals(this.name)) { 
            isFieldPresent = true; 
        } 
        return cv.visitField(access, name, desc, signature, value); 
    } 

    @Override 
    public void visitEnd() { 
        if (!isFieldPresent) { 
            FieldVisitor fv = cv.visitField(accessModifier, name, desc, null, null); 
            if (fv != null) { 
                fv.visitEnd(); 
            } 
        } 
        cv.visitEnd(); 
    } 


</pre> <br /><strong>3,添加属性的工具 AddField.java</strong> <br /><pre name="code" class="java"> 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 

import org.objectweb.asm.ClassAdapter; 
import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.ClassWriter; 
import org.objectweb.asm.Opcodes; 

public class AddField { 

    private Class clazz = null; 
    private ClassReader cr = null; 
    private ClassWriter cw = null; 
    private ClassAdapter ca = null; 
    private File classFile = null; 

    private final static String CLASS_FILE_SUFFIX = ".class"; 

    public AddField(Class clazz) { 
        this.clazz = clazz; 
    } 

    /** 
     * 添加一个 public 的类成员 
     * @param fieldName     类成员名 
     * @param fieldDesc     类成员类型描述 
     */ 
    public void addPublicField(String fieldName, String fieldDesc) { 
        if(cr == null) { 
            try { 
                cr = new ClassReader(clazz.getCanonicalName()); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
            cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); 
        } 
        if(ca == null) { 
            ca = new AddFieldAdapter(cw, Opcodes.ACC_PUBLIC, fieldName, fieldDesc); 
        } else { 
            ca = new AddFieldAdapter(ca, Opcodes.ACC_PUBLIC, fieldName, fieldDesc); 
        } 
    } 

    /** 
     * 将字节码写入类的 .class 文件 
     * 
     */ 
    public void writeByteCode() { 
        cr.accept(ca, ClassReader.SKIP_DEBUG); 
        byte[] bys = cw.toByteArray(); 
        OutputStream os = null; 
        try { 
            os = new FileOutputStream(getFile()); 
            os.write(bys); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } finally { 
            try { 
                os.close(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
    } 

    /** 
     * 获得类文件的 File 对象 
     * @return 
     */ 
    private File getFile() { 
        if(classFile == null) { 
            StringBuffer sb = new StringBuffer(); 
            sb.append(clazz.getResource("/")) 
                .append(clazz.getCanonicalName().replace(".", File.separator)) 
                .append(CLASS_FILE_SUFFIX); 
            classFile = new File(sb.substring(6)); 
        } 
        return classFile; 
    } 

</pre> <br /><strong>4,字节码处理:PreCompileProcess.java</strong> <br /><pre name="code" class="java"> 
public class PreCompileProcess { 

    public static void main(String[] args) { 

        // 为 Student 添加字段 
        AddField add = new AddField(Student.class); 

        // 添加一个名为 address,类型为 java.lang.String 的 public 字段 
        add.addPublicField("address", "Ljava/lang/String;"); 

        // 再增加一个名为 tel,类型为 int 的 public 方法 
        add.addPublicField("tel", "I"); 

        // 重新生成 .class 文件 
        add.writeByteCode(); 
    } 

</pre> <br /><strong>5,测试类:Test.java</strong> <br /><pre name="code" class="java"> 
public class Test { 

    public static void main(String[] args) { 
        Student stu = new Student(); 
        stu.setAge(10); 
        stu.setName("Tom"); 
        stu.address = "Beijing";    // 新增加的 address 字段 
        stu.tel = 56;               // 新增加的 tel 字段 
        System.out.println("Name:    " + stu.getName()); 
        System.out.println("Age:     " + stu.getAge()); 
        System.out.println("Address: " + stu.address); 
        System.out.println("Tel:     " + stu.tel); 
    } 

</pre> <br /></div> <br />帅哥,我刚打完球,看了一下,怎么还是通过方法获取属性的,我想表达的意思是通过属性!

问题补充:<div class="quote_title">jbutton 写道</div><div class="quote_div">通过程序修改 .class 文件!<strong>&lt;&lt;希望你参考下&gt;&gt;</strong> <br />下面这个是用 ASM 工具为 Student 类添加一个 public String 类型的 address 属性: <br /><strong>1,需要添加属性的原始类:Student.java</strong> <br /><pre name="code" class="java"> 
public class Student { 
    private int age; 
    private String name; 
    public int getAge() { 
        return age; 
    } 
    public void setAge(int age) { 
        this.age = age; 
    } 
    public String getName() { 
        return name; 
    } 
    public void setName(String name) { 
        this.name = name; 
    }    

</pre> <br /><strong>2,添加属性的适配器:AddFieldAdapter.java</strong> <br /><pre name="code" class="java"> 
import org.objectweb.asm.ClassAdapter; 
import org.objectweb.asm.ClassVisitor; 
import org.objectweb.asm.FieldVisitor; 

public class AddFieldAdapter extends ClassAdapter { 
    private int accessModifier; 
    private String name; 
    private String desc; 
    private boolean isFieldPresent; 

    public AddFieldAdapter(ClassVisitor cv, int accessModifier, String name, String desc) { 
        super(cv); 
        this.accessModifier = accessModifier; 
        this.name = name; 
        this.desc = desc; 
    } 

    @Override 
    public FieldVisitor visitField(int access, String name, String desc, 
            String signature, Object value) { 
        if (name.equals(this.name)) { 
            isFieldPresent = true; 
        } 
        return cv.visitField(access, name, desc, signature, value); 
    } 

    @Override 
    public void visitEnd() { 
        if (!isFieldPresent) { 
            FieldVisitor fv = cv.visitField(accessModifier, name, desc, null, null); 
            if (fv != null) { 
                fv.visitEnd(); 
            } 
        } 
        cv.visitEnd(); 
    } 


</pre> <br /><strong>3,添加属性的工具 AddField.java</strong> <br /><pre name="code" class="java"> 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 

import org.objectweb.asm.ClassAdapter; 
import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.ClassWriter; 
import org.objectweb.asm.Opcodes; 

public class AddField { 

    private Class clazz = null; 
    private ClassReader cr = null; 
    private ClassWriter cw = null; 
    private ClassAdapter ca = null; 
    private File classFile = null; 

    private final static String CLASS_FILE_SUFFIX = ".class"; 

    public AddField(Class clazz) { 
        this.clazz = clazz; 
    } 

    /** 
     * 添加一个 public 的类成员 
     * @param fieldName     类成员名 
     * @param fieldDesc     类成员类型描述 
     */ 
    public void addPublicField(String fieldName, String fieldDesc) { 
        if(cr == null) { 
            try { 
                cr = new ClassReader(clazz.getCanonicalName()); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
            cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); 
        } 
        if(ca == null) { 
            ca = new AddFieldAdapter(cw, Opcodes.ACC_PUBLIC, fieldName, fieldDesc); 
        } else { 
            ca = new AddFieldAdapter(ca, Opcodes.ACC_PUBLIC, fieldName, fieldDesc); 
        } 
    } 

    /** 
     * 将字节码写入类的 .class 文件 
     * 
     */ 
    public void writeByteCode() { 
        cr.accept(ca, ClassReader.SKIP_DEBUG); 
        byte[] bys = cw.toByteArray(); 
        OutputStream os = null; 
        try { 
            os = new FileOutputStream(getFile()); 
            os.write(bys); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } finally { 
            try { 
                os.close(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
    } 

    /** 
     * 获得类文件的 File 对象 
     * @return 
     */ 
    private File getFile() { 
        if(classFile == null) { 
            StringBuffer sb = new StringBuffer(); 
            sb.append(clazz.getResource("/")) 
                .append(clazz.getCanonicalName().replace(".", File.separator)) 
                .append(CLASS_FILE_SUFFIX); 
            classFile = new File(sb.substring(6)); 
        } 
        return classFile; 
    } 

</pre> <br /><strong>4,字节码处理:PreCompileProcess.java</strong> <br /><pre name="code" class="java"> 
public class PreCompileProcess { 

    public static void main(String[] args) { 

        // 为 Student 添加字段 
        AddField add = new AddField(Student.class); 

        // 添加一个名为 address,类型为 java.lang.String 的 public 字段 
        add.addPublicField("address", "Ljava/lang/String;"); 

        // 再增加一个名为 tel,类型为 int 的 public 方法 
        add.addPublicField("tel", "I"); 

        // 重新生成 .class 文件 
        add.writeByteCode(); 
    } 

</pre> <br /><strong>5,测试类:Test.java</strong> <br /><pre name="code" class="java"> 
public class Test { 

    public static void main(String[] args) { 
        Student stu = new Student(); 
        stu.setAge(10); 
        stu.setName("Tom"); 
        stu.address = "Beijing";    // 新增加的 address 字段 
        stu.tel = 56;               // 新增加的 tel 字段 
        System.out.println("Name:    " + stu.getName()); 
        System.out.println("Age:     " + stu.getAge()); 
        System.out.println("Address: " + stu.address); 
        System.out.println("Tel:     " + stu.tel); 
    } 

</pre> <br /></div> <br />这是一道thinking in patters上的练习题!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值