#903 - Refactor: Internals, BeanPropertyAccess getter and setter methods can be cached and don't need constructor

This commit is contained in:
Rob Bygrave
2016-11-28 22:02:45 +13:00
parent 85bb05d90e
commit a585447dc9
7 changed files with 106 additions and 161 deletions
@@ -45,9 +45,8 @@ import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil;
import com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations;
import com.avaje.ebeaninternal.server.deploy.parse.TransientProperties;
import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfoFactory;
import com.avaje.ebeaninternal.server.properties.EnhanceBeanPropertyInfoFactory;
import com.avaje.ebeaninternal.server.properties.BeanPropertyAccess;
import com.avaje.ebeaninternal.server.properties.EnhanceBeanPropertyAccess;
import com.avaje.ebeaninternal.xmlmapping.XmlMappingReader;
import com.avaje.ebeaninternal.xmlmapping.model.XmAliasMapping;
import com.avaje.ebeaninternal.xmlmapping.model.XmColumnMapping;
@@ -98,7 +97,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
*/
private final DeployInherit deplyInherit;
private final BeanPropertyInfoFactory reflectFactory;
private final BeanPropertyAccess beanPropertyAccess = new EnhanceBeanPropertyAccess();
private final DeployUtil deployUtil;
@@ -225,7 +224,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
this.beanQueryAdapterManager = new BeanQueryAdapterManager(bootupClasses);
this.beanFinderManager = new BeanFinderManager(bootupClasses);
this.reflectFactory = createReflectionFactory();
this.transientProperties = new TransientProperties();
this.changeLogPrepare = config.changeLogPrepare(bootupClasses.getChangeLogPrepare());
this.changeLogListener = config.changeLogListener(bootupClasses.getChangeLogListener());
@@ -1312,11 +1310,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
}
}
private BeanPropertyInfoFactory createReflectionFactory() {
return new EnhanceBeanPropertyInfoFactory();
}
/**
* Set BeanReflect BeanReflectGetter and BeanReflectSetter properties.
* <p>
@@ -1331,11 +1324,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
// use generated code. NB: Due to Bug 166 so now doing this for
// abstract classes as well.
Class<?> beanType = desc.getBeanType();
BeanPropertiesReader reflectProps = new BeanPropertiesReader(beanType);
BeanPropertyInfo beanReflect = reflectFactory.create(beanType);
BeanPropertiesReader reflectProps = new BeanPropertiesReader(desc.getBeanType());
desc.setProperties(reflectProps.getProperties());
for (DeployBeanProperty prop : desc.propertiesAll()) {
@@ -1343,14 +1332,14 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
Integer pos = reflectProps.getPropertyIndex(propName);
if (pos == null) {
if (isPersistentField(prop)) {
throw new IllegalStateException("Property " + propName + " not found in " + reflectProps + " for type " + beanType);
throw new IllegalStateException("Property " + propName + " not found in " + reflectProps + " for type " + desc.getBeanType());
}
} else {
final int propertyIndex = pos;
prop.setPropertyIndex(propertyIndex);
prop.setGetter(beanReflect.getGetter(propertyIndex));
prop.setSetter(beanReflect.getSetter(propertyIndex));
prop.setGetter(beanPropertyAccess.getGetter(propertyIndex));
prop.setSetter(beanPropertyAccess.getSetter(propertyIndex));
if (prop.isAggregation()) {
prop.setAggregationPrefix(DetermineAggPath.manyPath(prop.getAggregation(), desc));
}
@@ -0,0 +1,17 @@
package com.avaje.ebeaninternal.server.properties;
/**
* Provides getter setter methods for beans.
*/
public interface BeanPropertyAccess {
/**
* Return the getter for a given bean property.
*/
BeanPropertyGetter getGetter(int position);
/**
* Return the setter for a given bean property.
*/
BeanPropertySetter getSetter(int position);
}
@@ -1,26 +0,0 @@
package com.avaje.ebeaninternal.server.properties;
/**
* Provides getter setter and construction methods for beans.
* <p>
* This enables the implementation to use standard reflection or
* code generation.
* </p>
*/
public interface BeanPropertyInfo {
/**
* Create an EntityBean for this type.
*/
Object createEntityBean();
/**
* Return the getter for a given bean property.
*/
BeanPropertyGetter getGetter(int position);
/**
* Return the setter for a given bean property.
*/
BeanPropertySetter getSetter(int position);
}
@@ -1,14 +0,0 @@
package com.avaje.ebeaninternal.server.properties;
/**
* Creates BeanReflect object used to provide getter setter and construction
* for the beans.
*/
public interface BeanPropertyInfoFactory {
/**
* Create the BeanReflect for the given plain bean and its EntityBean equivalent.
*/
BeanPropertyInfo create(Class<?> entityBeanType);
}
@@ -0,0 +1,82 @@
package com.avaje.ebeaninternal.server.properties;
import com.avaje.ebean.bean.EntityBean;
/**
* Returns Getter and Setter methods based on EntityBean enhancement and field position.
*/
public final class EnhanceBeanPropertyAccess implements BeanPropertyAccess {
private static final int CACHE_SIZE = 30;
private final BeanPropertyGetter[] getters = initGetters(CACHE_SIZE);
private final BeanPropertySetter[] setters = initSetters(CACHE_SIZE);
public EnhanceBeanPropertyAccess() {
}
private BeanPropertyGetter[] initGetters(int count) {
BeanPropertyGetter[] getters = new BeanPropertyGetter[count];
for (int i = 0; i < count; i++) {
getters[i] = new Getter(i);
}
return getters;
}
private BeanPropertySetter[] initSetters(int count) {
BeanPropertySetter[] setters = new BeanPropertySetter[count];
for (int i = 0; i < count; i++) {
setters[i] = new Setter(i);
}
return setters;
}
public BeanPropertyGetter getGetter(int position) {
if (position < CACHE_SIZE) {
return getters[position];
}
return new Getter(position);
}
public BeanPropertySetter getSetter(int position) {
if (position < CACHE_SIZE) {
return setters[position];
}
return new Setter(position);
}
private static final class Getter implements BeanPropertyGetter {
private final int fieldIndex;
Getter(int fieldIndex) {
this.fieldIndex = fieldIndex;
}
public Object get(EntityBean bean) {
return bean._ebean_getField(fieldIndex);
}
public Object getIntercept(EntityBean bean) {
return bean._ebean_getFieldIntercept(fieldIndex);
}
}
private static final class Setter implements BeanPropertySetter {
private final int fieldIndex;
Setter(int fieldIndex) {
this.fieldIndex = fieldIndex;
}
public void set(EntityBean bean, Object value) {
bean._ebean_setField(fieldIndex, value);
}
public void setIntercept(EntityBean bean, Object value) {
bean._ebean_setFieldIntercept(fieldIndex, value);
}
}
}
@@ -1,90 +0,0 @@
package com.avaje.ebeaninternal.server.properties;
import com.avaje.ebean.bean.EntityBean;
import javax.persistence.PersistenceException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
/**
* A BeanReflect implementation based on the enhancement that creates EntityBean
* implementations.
*/
public final class EnhanceBeanPropertyInfo implements BeanPropertyInfo {
private static final Object[] constuctorArgs = new Object[0];
private final Constructor<?> constructor;
public EnhanceBeanPropertyInfo(Class<?> clazz) {
try {
if (Modifier.isAbstract(clazz.getModifiers())) {
this.constructor = null;
} else {
this.constructor = defaultConstructor(clazz);
}
} catch (Exception e) {
throw new PersistenceException(e);
}
}
private Constructor<?> defaultConstructor(Class<?> cls) {
try {
Class<?>[] params = new Class[0];
return cls.getDeclaredConstructor(params);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public Object createEntityBean() {
try {
return constructor.newInstance(constuctorArgs);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public BeanPropertyGetter getGetter(int position) {
return new Getter(position);
}
public BeanPropertySetter getSetter(int position) {
return new Setter(position);
}
static final class Getter implements BeanPropertyGetter {
private final int fieldIndex;
Getter(int fieldIndex) {
this.fieldIndex = fieldIndex;
}
public Object get(EntityBean bean) {
return bean._ebean_getField(fieldIndex);
}
public Object getIntercept(EntityBean bean) {
return bean._ebean_getFieldIntercept(fieldIndex);
}
}
static final class Setter implements BeanPropertySetter {
private final int fieldIndex;
Setter(int fieldIndex) {
this.fieldIndex = fieldIndex;
}
public void set(EntityBean bean, Object value) {
bean._ebean_setField(fieldIndex, value);
}
public void setIntercept(EntityBean bean, Object value) {
bean._ebean_setFieldIntercept(fieldIndex, value);
}
}
}
@@ -1,13 +0,0 @@
package com.avaje.ebeaninternal.server.properties;
/**
* Creates a BeanReflectFactory based on the enhancement that
* creates EntityBean implementations.
*/
public final class EnhanceBeanPropertyInfoFactory implements BeanPropertyInfoFactory {
public BeanPropertyInfo create(Class<?> entityBeanType) {
return new EnhanceBeanPropertyInfo(entityBeanType);
}
}