Code generation library for creating dynamic proxies, bean utilities, and fast reflection alternatives with bundled dependencies
—
Essential utilities for key generation, transformations, predicates, string switching, parallel sorting, and low-level code generation support. These utilities provide foundational functionality used throughout CGLib and are also useful for application development.
Generates classes for multi-valued keys with proper equals/hashCode implementations.
/**
* Generates classes for multi-valued keys with proper equals/hashCode
*/
public abstract class KeyFactory {
/**
* Built-in customizer for class-by-name comparison
*/
public static final Customizer CLASS_BY_NAME;
/**
* Built-in customizer for object-by-class comparison
*/
public static final Customizer OBJECT_BY_CLASS;
/**
* Key factory for ASM types
*/
public static final KeyFactory HASH_ASM_TYPE;
/**
* Create key factory for interface
* @param keyInterface Interface defining key structure
* @return KeyFactory instance
*/
public static KeyFactory create(Class keyInterface);
/**
* Create key factory with customizer
* @param keyInterface Interface defining key structure
* @param customizer Customizer for key generation
* @return KeyFactory instance
*/
public static KeyFactory create(Class keyInterface, Customizer customizer);
/**
* Create key factory with multiple customizers
* @param keyInterface Interface defining key structure
* @param first First customizer
* @param next Additional customizers
* @return KeyFactory instance
*/
public static KeyFactory create(Class keyInterface, KeyFactoryCustomizer first, List<KeyFactoryCustomizer> next);
/**
* Create key factory with specific ClassLoader
* @param loader ClassLoader to use
* @param keyInterface Interface defining key structure
* @param customizer Customizer for key generation
* @return KeyFactory instance
*/
public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer);
/**
* Create key instance
* @param args Values for key fields
* @return Key instance
*/
public abstract Object newInstance(Object[] args);
}Usage Examples:
// Define key interface
interface CacheKey {
// Key fields are inferred from interface methods
// equals/hashCode will be generated automatically
}
// Create key factory
KeyFactory keyFactory = KeyFactory.create(CacheKey.class);
// Create key instances
CacheKey key1 = (CacheKey) keyFactory.newInstance(new Object[]{"user", 123, "profile"});
CacheKey key2 = (CacheKey) keyFactory.newInstance(new Object[]{"user", 123, "profile"});
CacheKey key3 = (CacheKey) keyFactory.newInstance(new Object[]{"user", 456, "profile"});
// Keys with same values are equal
assert key1.equals(key2); // true
assert key1.hashCode() == key2.hashCode(); // true
assert !key1.equals(key3); // false
// Use in HashMap
Map<CacheKey, Object> cache = new HashMap<>();
cache.put(key1, "cached data");
Object data = cache.get(key2); // "cached data" - works because key1.equals(key2)
// Multi-field key interface
interface DatabaseKey {
String getTable();
Long getId();
String getOperation();
}
KeyFactory dbKeyFactory = KeyFactory.create(DatabaseKey.class);
DatabaseKey dbKey = (DatabaseKey) dbKeyFactory.newInstance(new Object[]{"users", 123L, "select"});
// Custom comparison with customizer
KeyFactory customFactory = KeyFactory.create(CacheKey.class, new Customizer() {
public void customize(CodeEmitter e, Type type) {
// Custom hash/equals logic if needed
}
});Interface for converting values during operations like bean copying.
/**
* Interface for converting values during operations
*/
public interface Converter {
/**
* Convert a value from one type to another
* @param value Source value
* @param target Target type
* @param context Context information (often property name)
* @return Converted value
*/
Object convert(Object value, Class target, Object context);
}Usage Examples:
// Date to String converter
Converter dateConverter = new Converter() {
public Object convert(Object value, Class target, Object context) {
if (value instanceof Date && target == String.class) {
return new SimpleDateFormat("yyyy-MM-dd").format((Date) value);
}
if (value instanceof String && target == Date.class) {
try {
return new SimpleDateFormat("yyyy-MM-dd").parse((String) value);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
return value;
}
};
// Use with BeanCopier
BeanCopier copier = BeanCopier.create(SourceBean.class, TargetBean.class, true);
SourceBean source = new SourceBean();
source.setCreatedDate(new Date());
TargetBean target = new TargetBean();
copier.copy(source, target, dateConverter);
// target.createdDate is now a String
// Type-safe converter
Converter numberConverter = new Converter() {
public Object convert(Object value, Class target, Object context) {
if (value == null) return null;
if (target == Integer.class || target == int.class) {
return Integer.valueOf(value.toString());
}
if (target == Double.class || target == double.class) {
return Double.valueOf(value.toString());
}
if (target == String.class) {
return value.toString();
}
return value;
}
};Interface for transforming objects.
/**
* Interface for transforming objects
*/
public interface Transformer {
/**
* Transform a value
* @param value Input value
* @return Transformed value
*/
Object transform(Object value);
}Usage Examples:
// String transformer
Transformer upperCaseTransformer = new Transformer() {
public Object transform(Object value) {
return value != null ? value.toString().toUpperCase() : null;
}
};
// Number transformer
Transformer doubleTransformer = new Transformer() {
public Object transform(Object value) {
if (value instanceof Number) {
return ((Number) value).doubleValue() * 2;
}
return value;
}
};
// Chain transformers
Transformer chainedTransformer = new Transformer() {
public Object transform(Object value) {
value = upperCaseTransformer.transform(value);
value = doubleTransformer.transform(value);
return value;
}
};
// Use with collections
List<String> names = Arrays.asList("alice", "bob", "charlie");
List<String> upperNames = names.stream()
.map(name -> (String) upperCaseTransformer.transform(name))
.collect(Collectors.toList());Interface for boolean predicates used for filtering.
/**
* Interface for boolean predicates
*/
public interface Predicate {
/**
* Evaluate predicate
* @param arg Input argument
* @return true if predicate matches
*/
boolean evaluate(Object arg);
}Usage Examples:
// String length predicate
Predicate longStringPredicate = new Predicate() {
public boolean evaluate(Object arg) {
return arg instanceof String && ((String) arg).length() > 5;
}
};
// Number range predicate
Predicate positiveNumberPredicate = new Predicate() {
public boolean evaluate(Object arg) {
return arg instanceof Number && ((Number) arg).doubleValue() > 0;
}
};
// Use for filtering
List<String> words = Arrays.asList("cat", "elephant", "dog", "hippopotamus");
List<String> longWords = new ArrayList<>();
for (String word : words) {
if (longStringPredicate.evaluate(word)) {
longWords.add(word);
}
}
// longWords contains ["elephant", "hippopotamus"]
// Combine predicates
Predicate combinedPredicate = new Predicate() {
public boolean evaluate(Object arg) {
return longStringPredicate.evaluate(arg) &&
arg.toString().startsWith("e");
}
};Base class for code generation, providing common functionality for all CGLib generators.
/**
* Base class for all code generators in CGLib
*/
public abstract class AbstractClassGenerator<T> {
/**
* Set class loader for generated classes
* @param classLoader ClassLoader to use
*/
public void setClassLoader(ClassLoader classLoader);
/**
* Set prefix for generated class names
* @param namePrefix Name prefix
*/
public void setNamePrefix(String namePrefix);
/**
* Set naming policy for generated classes
* @param namingPolicy Naming policy
*/
public void setNamingPolicy(NamingPolicy namingPolicy);
/**
* Enable or disable caching of generated classes
* @param useCache Whether to use cache
*/
public void setUseCache(boolean useCache);
/**
* Set whether to attempt loading existing classes
* @param attemptLoad Whether to attempt load
*/
public void setAttemptLoad(boolean attemptLoad);
/**
* Set generation strategy
* @param strategy Generation strategy
*/
public void setStrategy(GeneratorStrategy strategy);
/**
* Generate class bytecode (implement in subclasses)
* @param v ClassVisitor for bytecode generation
* @throws Exception If generation fails
*/
public abstract void generateClass(ClassVisitor v) throws Exception;
/**
* Create instance (used internally)
* @param key Generation key
* @return Generated instance
*/
protected T create(Object key);
/**
* Get default ClassLoader
* @return Default ClassLoader
*/
protected ClassLoader getDefaultClassLoader();
/**
* Get protection domain for generated classes
* @return ProtectionDomain
*/
protected ProtectionDomain getProtectionDomain();
/**
* Create first instance of generated class
* @param type Generated class
* @return First instance
* @throws Exception If creation fails
*/
protected Object firstInstance(Class type) throws Exception;
/**
* Create additional instances
* @param instance Existing instance
* @return New instance
* @throws Exception If creation fails
*/
protected Object nextInstance(Object instance) throws Exception;
}Controls naming of generated classes.
/**
* Policy for naming generated classes
*/
public interface NamingPolicy {
/**
* Generate class name
* @param prefix Name prefix
* @param source Source information
* @param key Generation key
* @param names Predicate for checking name conflicts
* @return Generated class name
*/
String getClassName(String prefix, String source, Object key, Predicate names);
}Controls class generation strategy.
/**
* Strategy for class generation
*/
public interface GeneratorStrategy {
/**
* Generate bytecode
* @param cg Class generator
* @return Generated bytecode
* @throws Exception If generation fails
*/
byte[] generate(ClassGenerator cg) throws Exception;
/**
* Check equality
* @param o Other object
* @return true if equal
*/
boolean equals(Object o);
}Customizes key generation in KeyFactory.
/**
* Customizer for key generation
*/
public interface Customizer extends KeyFactoryCustomizer {
/**
* Customize code emission for key generation
* @param e Code emitter
* @param type Type being processed
*/
void customize(CodeEmitter e, Type type);
}Install with Tessl CLI
npx tessl i tessl/maven-cglib--cglib-nodep