動態修改實體class類註釋中的值
阿新 • • 發佈:2019-02-02
import java.lang.reflect.Method; import javassist.ClassPool; import javassist.CtClass; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.ClassFile; import javassist.bytecode.ConstPool; import javassist.bytecode.annotation.Annotation; import javassist.bytecode.annotation.ArrayMemberValue; import javassist.bytecode.annotation.BooleanMemberValue; import javassist.bytecode.annotation.IntegerMemberValue; import javassist.bytecode.annotation.MemberValue; import javassist.bytecode.annotation.StringMemberValue; /** * @Title: ClassPoolUtils.java * @Package com.sgfm.scsm.util * @Description: 動態修改實體類註釋中的值(不提倡經常使用) * @author TangCai * @date 2016年11月16日 下午3:08:56 * @version V1.0 */ public class ClassPoolUtils { /** * 執行時動態ORM表對映 * @param entityClass 實體類 * @param annotation 註釋類 * @param atMethodName 註釋類方法 * @param atMethodVal 註釋類方法的更新值 * @return 修改註釋值後實體類 */ @SuppressWarnings("unchecked") public static Class<?> setPool(Class<?> entityClass, Class<?> annotation, String atMethodName, Object atMethodVal){ Class<?> c = null; try { ClassPool classPool = ClassPool.getDefault(); CtClass clazz = classPool.getCtClass(entityClass.getName()); ClassFile classFile = clazz.getClassFile(); //clazz.freeze();//凍結 ConstPool constPool = classFile.getConstPool(); Class<java.lang.annotation.Annotation> cl = (Class<java.lang.annotation.Annotation>)annotation; Annotation newAnnotation = createJavassistAnnotation(constPool,entityClass.getAnnotation(cl),atMethodName,atMethodVal); AnnotationsAttribute attribute = (AnnotationsAttribute)classFile.getAttribute(AnnotationsAttribute.visibleTag); attribute.addAnnotation(newAnnotation); classFile.addAttribute(attribute); ClassLoader parent = entityClass.getClassLoader(); EntityClassLoader loader = new ClassPoolUtils().new EntityClassLoader(parent); //clazz.toClass();//同一個ClassLoader不能多次載入同一個類 c = clazz.toClass(loader , null);//替換Class的時候, 載入該Class的ClassLoader也必須用新的 //clazz.defrost();//解除凍結 clazz.detach(); //登出class } catch (Exception e) { e.printStackTrace(); } return c; } public static Annotation createJavassistAnnotation(ConstPool constpool, java.lang.annotation.Annotation annotation,String atMethodName, Object atMethodVal) throws Exception { Annotation annotationCopy = new Annotation(annotation.annotationType().getName(), constpool); String typeName = null; MemberValue mv = null; for (Method m : annotation.annotationType().getDeclaredMethods()) { Object value = m.invoke(annotation); typeName = m.getReturnType().getSimpleName(); if(atMethodName.equals(m.getName())) value = atMethodVal; if(typeName.equals("int")) mv = new IntegerMemberValue(constpool,(Integer)value); else if(typeName.equals("String[]")){ String[] stres = (String[])value; StringMemberValue[] elements = new StringMemberValue[stres.length]; for(int i=0;i<stres.length;i++) elements[i] = new StringMemberValue(stres[i],constpool); ArrayMemberValue amv = new ArrayMemberValue(constpool); amv.setValue(elements); mv = amv; } else if(typeName.equals("boolean")) mv = new BooleanMemberValue((Boolean)value,constpool); else mv = new StringMemberValue(value.toString(),constpool); annotationCopy.addMemberValue(m.getName(),mv); } return annotationCopy; } /** * @Title: EntityClassLoader.java * @Package com.sgfm.scsm.util * @Description: 實體類載入器 * 該載入器主要用於執行時動態修改實體後,重新裝載實體 * @author TangCai * @date 2016年11月16日 下午3:18:55 * @version V1.0 */ public class EntityClassLoader extends ClassLoader { private ClassLoader parent; public EntityClassLoader(ClassLoader parent){ this.parent = parent; } @Override public Class<?> loadClass(String name) throws ClassNotFoundException { return this.loadClass(name, false); } @Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { Class<?> clazz = this.findLoadedClass(name); if(null != parent) clazz = parent.loadClass(name); if(null == clazz) this.findSystemClass(name); if(null == clazz) throw new ClassNotFoundException(); if(null != clazz && resolve) this.resolveClass(clazz); return clazz; } } }