net.sf.juffrou.util.reflect.BeanWrapperFactory Maven / Gradle / Ivy
Show all versions of juffrou-reflect Show documentation
package net.sf.juffrou.util.reflect;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import net.sf.juffrou.error.BeanInstanceBuilderException;
/**
* This class is responsible for creating and caching BeanWrapperContexts.
* A BeanWrapper uses the same BeanWrapperFactory to create the BeanWrapperContexts for its nested BeanWrappers.
* BeanWrapperFactory can also be used as an umbrella to create BeanWrappers in a more performant way as it caches
* the introspection information and re-uses it whenever possible.
* @author cemartins
*/
public class BeanWrapperFactory {
private final Map classContextMap = new HashMap();
// preferences info
private BeanInstanceBuilder beanInstanceCreator = null;
private BeanContextBuilder beanContextCreator = null;
/**
* Retrieves a BeanWrapperContext for java bean class.
* If the BeanWrapperContext is not in cache then creates a new one.
* @param clazz the bean class to inspect
* @return a BeanWrapperContext with introspection information about the specified class.
* @see {@link #getBeanWrapperContext(Class, Type...)}
*/
public BeanWrapperContext getBeanWrapperContext(Class clazz) {
return getBeanWrapperContext(clazz, null);
}
/**
* Retrieves a BeanWrapperContext for a parameterized (generic) java bean class.
* If the BeanWrapperContext is not in cache then creates a new one.
* @param clazz the generic bean class to inspect.
* @param types the parameters that defined the generic bean class.
* @return a BeanWrapperContext with introspection information about the specified class.
*/
public BeanWrapperContext getBeanWrapperContext(Class clazz, Type... types) {
BeanWrapperContext context = classContextMap.get(clazz);
if(context == null) {
context = getBeanContextBuilder().build(this, clazz, types);
classContextMap.put(clazz, context);
}
return context;
}
/**
* Construct a bean wrapper around a class.
* Bean instances will be instances of that class and will be created only when necessary.
* Try to use a cached BeanWrapperContext to save introspection time.
* @param clazz class to instantiate the wrapped bean
*/
public BeanWrapper getBeanWrapper(Class clazz) {
return new BeanWrapper(getBeanWrapperContext(clazz));
}
/**
* Construct a bean wrapper around an existing bean instance.
* Will try to use a cached BeanWrapperContext to save introspection time.
* @param instance the bean object to be wrapped
*/
public BeanWrapper getBeanWrapper(Object instance) {
return new BeanWrapper(getBeanWrapperContext(instance.getClass(), null), instance);
}
protected BeanInstanceBuilder getBeanInstanceBuilder() {
if(beanInstanceCreator == null)
beanInstanceCreator = new DefaultBeanInstanceCreator();
return beanInstanceCreator;
}
/**
* Control the instantiation of beans and wrapped beans.
* The bean wrapper creates new instances using Class.newIntance() by default.
* You can use this this if you want to create class instances yourself.
* @param beanInstanceBuilder
*/
public void setBeanInstanceBuilder(BeanInstanceBuilder beanInstanceBuilder) {
this.beanInstanceCreator = beanInstanceBuilder;
}
private BeanContextBuilder getBeanContextBuilder() {
if(beanContextCreator == null)
beanContextCreator = new DefaultBeanContextCreator();
return beanContextCreator;
}
/**
* Control the creation of BeanWrapperContexts.
* Provide a custom BeanContextBuilder that will instantiate your custom BeanWrapperContext. This way
* you can extend the BeanWrapperContext class and attach more information to a bean.
* @param beanContextBuilder
*/
public void setBeanContextBuilder(BeanContextBuilder beanContextBuilder) {
this.beanContextCreator = beanContextBuilder;
}
private static class DefaultBeanInstanceCreator implements BeanInstanceBuilder {
@Override
public Object build(Class clazz) throws BeanInstanceBuilderException {
Object instance;
try {
instance = clazz.newInstance();
} catch (InstantiationException e) {
throw new BeanInstanceBuilderException(e);
} catch (IllegalAccessException e) {
throw new BeanInstanceBuilderException(e);
}
return instance;
}
}
private static class DefaultBeanContextCreator implements BeanContextBuilder {
@Override
public BeanWrapperContext build(BeanWrapperFactory factory, Class clazz, Type... types) {
return new BeanWrapperContext(factory, clazz, types);
}
}
}