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

net.minidev.asm.BeansAccess Maven / Gradle / Ivy

Go to download

Java reflect give poor performance on getter setter an constructor calls, accessors-smart use ASM to speed up those calls.

The newest version!
package net.minidev.asm;

/*
 *    Copyright 2011-2023 JSON-SMART authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Allow access reflect field using runtime generated accessor. BeansAccessor is
 * faster than java.lang.reflect.Method.invoke()
 * 
 * @param  the type of the bean being accessed
 * @author uriel Chemouni
 */
public abstract class BeansAccess {
	/**
	 * default constuctor
	 */
	public BeansAccess() {
		super();
	}

	private HashMap map;
	private Accessor[] accs;

	/**
	 * set Accessor
	 * @param accs Accessor list
	 */
	protected void setAccessor(Accessor[] accs) {
		int i = 0;
		this.accs = accs;
		map = new HashMap();
		for (Accessor acc : accs) {
			acc.index = i++;
			map.put(acc.getName(), acc);
		}
	}

	/**
	 * get internal map
	 * @return a map
	 */
	public HashMap getMap() {
		return map;
	}

	/**
	 * get internal accessor
	 * @return Accessor list
	 */
	public Accessor[] getAccessors() {
		return accs;
	}

	/**
	 * cache used to store built BeansAccess
	 */
	private static ConcurrentHashMap, BeansAccess> cache = new ConcurrentHashMap, BeansAccess>();

	// private final static ConcurrentHashMap> cache;

	/**
	 * return the BeansAccess corresponding to a type
	 * 
	 * @param type to be access
	 * @param 

working type * @return the BeansAccess */ static public

BeansAccess

get(Class

type) { return get(type, null); } /** * return the BeansAccess corresponding to a type * * @param filter FieldFilter * @param type to be access * @param

working type * @return the BeansAccess */ static public

BeansAccess

get(Class

type, FieldFilter filter) { { @SuppressWarnings("unchecked") BeansAccess

access = (BeansAccess

) cache.get(type); if (access != null) return access; } // extract all access methods Accessor[] accs = ASMUtil.getAccessors(type, filter); // create new class name String className = type.getName(); String accessClassName; if (className.startsWith("java.util.")) accessClassName = "net.minidev.asm." + className + "AccAccess"; else accessClassName = className.concat("AccAccess"); // extend class base loader DynamicClassLoader loader = new DynamicClassLoader(type.getClassLoader()); // try to load existing class Class accessClass = null; try { accessClass = loader.loadClass(accessClassName); } catch (ClassNotFoundException ignored) { } LinkedList> parentClasses = getParents(type); // if the class do not exists build it if (accessClass == null) { BeansAccessBuilder builder = new BeansAccessBuilder(type, accs, loader); for (Class c : parentClasses) builder.addConversion(BeansAccessConfig.classMapper.get(c)); accessClass = builder.bulid(); } try { @SuppressWarnings("unchecked") BeansAccess

access = (BeansAccess

) accessClass.newInstance(); access.setAccessor(accs); cache.putIfAbsent(type, access); // add fieldname alias for (Class c : parentClasses) addAlias(access, BeansAccessConfig.classFiledNameMapper.get(c)); return access; } catch (Exception ex) { throw new RuntimeException("Error constructing accessor class: " + accessClassName, ex); } } /** * @param type current type * @return parents hierarchy */ private static LinkedList> getParents(Class type) { LinkedList> m = new LinkedList>(); while (type != null && !type.equals(Object.class)) { m.addLast(type); for (Class c : type.getInterfaces()) m.addLast(c); type = type.getSuperclass(); } m.addLast(Object.class); return m; } /** * @param access accessor to use * @param m mapping */ private static void addAlias(BeansAccess access, HashMap m) { // HashMap m = // BeansAccessConfig.classFiledNameMapper.get(type); if (m == null) return; HashMap changes = new HashMap(); for (Entry e : m.entrySet()) { Accessor a1 = access.map.get(e.getValue()); if (a1 != null) changes.put(e.getValue(), a1); } access.map.putAll(changes); } /** * set field value by field index * * @param object object to alter * @param methodIndex field id to update * @param value new value */ abstract public void set(T object, int methodIndex, Object value); /** * get field value by field index * @param object object to operate * @param methodIndex field number to operate * @return value of the field */ abstract public Object get(T object, int methodIndex); /** * create a new targeted object * @return new instance */ abstract public T newInstance(); /** * set field value by field name * @param object target object * @param methodName methodName * @param value new field value */ public void set(T object, String methodName, Object value) { int i = getIndex(methodName); if (i == -1) throw new net.minidev.asm.ex.NoSuchFieldException(methodName + " in " + object.getClass() + " to put value : " + value); set(object, i, value); } /** * get field value by field name * @param object object to operate * @param methodName getter to call * @return field value returned by the getter */ public Object get(T object, String methodName) { return get(object, getIndex(methodName)); } /** * Returns the index of the field accessor. * @param name field name * @return id of the field */ public int getIndex(String name) { Accessor ac = map.get(name); if (ac == null) return -1; return ac.index; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy