运行时动态修改注解

标签: 运行时 注解 | 发表时间:2012-09-21 16:43 | 作者:
出处:http://www.iteye.com

      由于当前项目采用了分表策略,故一个实体会对应多个相同结构的表。只是映射的表名不一样而已~项目又使用憨包儿呢特,让我采用原生SQL总感觉不是那么爽,咋办呢?!第一念头就是如果能够动态映射就好啦,也就是现在想查table1只需将实体对应的table映射为table1即可。咋个实现动态映射呢?!也就是需要动态改变类的注解。又咋个能够动态改变类的注解呢?!本质上修改字节码,重新加载类即可,也就是所谓的字节码增强功能~  看都看不懂字节码咋个修改呢?!还是需要站在巨人的肩上才行。ASM以及JDK自带的字节码增强都不用,马上想到CGlib,javassist。。。还是痛苦的折腾了良久,为了大家不走我的弯路~ 直接上代码先~

 

public class ClassPoolUtils {
    
    
    /**
     * 动态ORM映射
     * 
     * @param entityClassName   待映射的实体全限定类名
     * @param tableName         待映射的表名
     * @return                  映射后的类对象
     */
    public static Class<?> tableMapping(String entityClassName, String tableName){
        Class<?> c = null;
        try {
            ClassPool classPool = ClassPool.getDefault();
            classPool.appendClassPath(new ClassClassPath(ClassPoolUtils.class));
            classPool.importPackage("javax.persistence");
            CtClass clazz = classPool.get(entityClassName);
            ClassFile classFile = clazz.getClassFile();
           
            System.out.println("增强前Entity01:" + clazz.getAnnotation(Entity.class));
            System.out.println("增强前Table02:" + clazz.getAnnotation(Table.class));
            
            ConstPool constPool = classFile.getConstPool();
            Annotation tableAnnotation = new Annotation("javax.persistence.Table", constPool);
            tableAnnotation.addMemberValue("name", new StringMemberValue(tableName, constPool));
            // 获取运行时注解属性
            AnnotationsAttribute attribute = (AnnotationsAttribute)classFile.getAttribute(AnnotationsAttribute.visibleTag);
            attribute.addAnnotation(tableAnnotation);
            classFile.addAttribute(attribute);
            classFile.setVersionToJava5();
            //clazz.writeFile();
            
            System.out.println("增强后Entity001:" + clazz.getAnnotation(Entity.class));
            System.out.println("增强后Table002:" + clazz.getAnnotation(Table.class));
            //TODO 当前ClassLoader中必须尚未加载该实体。(同一个ClassLoader加载同一个类只会加载一次)
            c = clazz.toClass();
            System.out.println("增强后toClass-Entity0001:" + c.getAnnotation(Entity.class));
            System.out.println("增强后toClass-Table0002:" + c.getAnnotation(Table.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return c;
    }

    public static void main(String[] args) {     
          ClassPoolUtils.tableMapping("com.andy.model.Order", "order1");
    }

 

   执行结果:

 

写道
增强前Entity01:@javax.persistence.Entity
增强前Table02:null
增强后Entity001:@javax.persistence.Entity
增强后Table002:@javax.persistence.Table(name="order1")
增强后toClass-Entity0001:@javax.persistence.Entity(name=)
增强后toClass-Table0002:@javax.persistence.Table(schema=, catalog=, uniqueConstraints=[], name=order1)
 

已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [运行时 注解] 推荐:

运行时动态修改注解

- - ITeye博客
      由于当前项目采用了分表策略,故一个实体会对应多个相同结构的表. 只是映射的表名不一样而已~项目又使用憨包儿呢特,让我采用原生SQL总感觉不是那么爽,咋办呢. 第一念头就是如果能够动态映射就好啦,也就是现在想查table1只需将实体对应的table映射为table1即可. 本质上修改字节码,重新加载类即可,也就是所谓的字节码增强功能~  看都看不懂字节码咋个修改呢.

Android 运行时权限库

- - DiyCode - 致力于构建开发工程师高端交流分享社区社区
在项目的 build.gradle中,添加:. 在app的 build.gradle中,添加:. 创建一个 PermissionCompat.Builder对象. 设置弹出框,当 shouldShowRequestPermissionRationale() 返回true的时候,即用户已经拒绝了一次,给用户提示一个解释信息,为什么需要这个权限.

Mozilla Shumway:基于 HTML5 的 Flash 运行时

- - ITeye资讯频道
Mozilla 近日正式发布了完全使用 HTML5 技术实现的 SWF 运行时环境 Shumway. 和Mozilla另一产品pdf.js 类似, Shumway 完全使用 HTML5 技术构建,实现了一个 Flash 的图像、音频、视频以及 Actionscript 的 1 至 3 版本的运行时环境.

Java运行时的内存模型

- - CSDN博客编程语言推荐文章
每个线程单独的数据区(线程间不共享). 每个线程都有一片单独的内存区域,这里面包含:程序计数器(program counter register),JVM栈和本地方法栈(Native Method Stack). 当一个新的线程被创建的时候,这片内存就已经被分配出来了. 程序计数器:为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各线程之间的计数器互不影响,独立存储.

自己动手实现springboot运行时执行java源码(运行时编译、加载、注册bean、调用)

- - 掘金 后端
  看来断点、单步调试还不够硬核,根本没多少人看,这次再来个硬核的. 依然是由于apaas平台越来越流行了,如果apaas平台选择了java语言作为平台内的业务代码,那么不仅仅面临着IDE外的断点、单步调试,还面临着为了实现预览效果,需要将写好的java源码动态的装载到spring容器中然后调用源码内的某个方法.

[C++]运行时,如何确保一个对象是只读的

- Xin - 博客园-首页原创精华区
相信很多人碰到过一个问题,就是代码太多了,不知道在哪里把这个对象给修改掉了.这个其实有两种办法的.. 在调试的时候,可以下数据断点..   gdb有watch断点.比如gdb>watch *(int*)0x12433,要记住,如果想要一只监视这个数据,就要用地址,否则过了这个scope,数据断点就无效了,还有就是,监视的值如果用内置数据类型可以表达的话,是有硬件断点的,否则效率茫茫低......

使用gdb调试运行时的程序小技巧

- - 淘宝核心系统团队博客
转载请注明:转载自淘宝核心系统团队博客,谢谢. 原文链接地址: 使用gdb调试运行时的程序小技巧. 下面介绍我调试时经常遇到的三种问题,如果大家也有类似的问题交流一下解决方法:. 情景1:在不中止程序服务的情况下,怎么调试正在运行时的程序. 情景2:需要同时看几个变量的值或者批量查看多个core文件的堆栈信息怎么办.

JAVA内存结构之运行时数据区域

- - Java - 编程语言 - ITeye博客
1       内存区域. 1.1              运行时数据区域. Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线锃的启动和结束而建立和销毁.

Android下个版本将默认使用ART运行时

- - 博客园_新闻
ART 运行时已包含在 Android4.4 KitKat 中,我们都知道它最终将会替代旧的低效的 Dalvik 运行时. ART 在应用安装时就预编译字节码到机器语言,这一机制叫 Ahead-Of-Time (AOT)编译.