All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.firefly.utils.classproxy.FieldProxyFactoryUsingJavassist Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
package com.firefly.utils.classproxy;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.UUID;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;

import com.firefly.utils.ReflectUtils.FieldProxy;
import com.firefly.utils.collection.ConcurrentReferenceHashMap;
import com.firefly.utils.StringUtils;

public class FieldProxyFactoryUsingJavassist extends AbstractFieldProxyFactory {
	
	private static final Map fieldCache = new ConcurrentReferenceHashMap<>(256);
	public static final FieldProxyFactoryUsingJavassist INSTANCE = new FieldProxyFactoryUsingJavassist();

	private FieldProxyFactoryUsingJavassist() {}
	
	@Override
	public FieldProxy getFieldProxy(Field field) throws Throwable {
		FieldProxy ret = fieldCache.get(field);
		if(ret != null)
			return ret;
		
		synchronized(fieldCache) {
			ret = fieldCache.get(field);
			if(ret != null)
				return ret;
			
			ret = _getFieldProxy(field);
			fieldCache.put(field, ret);
			return ret;
		}
	}
	
	@SuppressWarnings("unchecked")
	private FieldProxy _getFieldProxy(Field field) throws Throwable {
//		long start = System.currentTimeMillis();
		ClassPool classPool = ClassPool.getDefault();
		classPool.insertClassPath(new ClassClassPath(FieldProxy.class));
//		classPool.importPackage(Field.class.getCanonicalName());
		
		CtClass cc = classPool.makeClass("com.firefly.utils.ProxyField" + UUID.randomUUID().toString().replace("-", ""));
		cc.addInterface(classPool.get(FieldProxy.class.getName()));
		cc.addField(CtField.make("private java.lang.reflect.Field field;", cc));
		
		CtConstructor constructor = new CtConstructor(new CtClass[]{classPool.get(Field.class.getName())}, cc);
		constructor.setBody("{this.field = (java.lang.reflect.Field)$1;}");
		cc.addConstructor(constructor);
		
		cc.addMethod(CtMethod.make("public java.lang.reflect.Field field(){return field;}", cc));
		cc.addMethod(CtMethod.make(createFieldGetterMethodCode(field), cc));
		cc.addMethod(CtMethod.make(createFieldSetterMethodCode(field), cc));
		
		FieldProxy ret = (FieldProxy) cc.toClass(classLoader, null).getConstructor(Field.class).newInstance(field);
//		long end = System.currentTimeMillis();
//		System.out.println("Javassist generates class proxy time -> " + (end - start));
		return ret;
	}

	private String createFieldGetterMethodCode(Field field) {
		Class fieldClazz = field.getType();
		StringBuilder code = new StringBuilder();
		code.append("public Object get(Object obj){\n")
			.append("\treturn ");
		
		boolean hasValueOf = false;
		if(fieldClazz.isPrimitive()) {
			code.append(StringUtils.replace("(Object){}.valueOf(", primitiveWrapMap.get(fieldClazz)));
			hasValueOf = true;
		}
		code.append(StringUtils.replace("(({})obj).{}", field.getDeclaringClass().getCanonicalName(), field.getName()));
		if(hasValueOf)
			code.append(")");
		
		code.append(";\n")
			.append("}");
		return code.toString();
	}
	
	private String createFieldSetterMethodCode(Field field) {
		Class fieldClazz = field.getType();
		StringBuilder code = new StringBuilder();
		code.append("public void set(Object obj, Object value){\n");
		code.append(StringUtils.replace("\t(({})obj).{} = ", field.getDeclaringClass().getCanonicalName(), field.getName()));
		
		if(fieldClazz.isPrimitive()) {
			code.append(StringUtils.replace("(({})value).{}Value()", primitiveWrapMap.get(fieldClazz), fieldClazz.getCanonicalName()));
		} else {
			code.append(StringUtils.replace("({})value", fieldClazz.getCanonicalName()));
		}
		code.append(";\n")
			.append("}");
		return code.toString();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy