By default db4o uses JdkReflector(Java) or NetReflector (.NET) as a GenericReflector delegate.
However, the programmer can instruct db4o to use a specially designed reflection implementation:
Java: Db4o.configure().reflectWith(reflector)
where reflector is one of the available reflectors or your own reflector implementation.
At present db4o comes with SelfReflector, which was designed for environments, which do not have built-in support for reflections (J2ME for example). In this implementation all the classes' information is stored in special registry. User classes should implement self_get and self_set methods to be registered individually and become "known" to SelfReflector.
Specific reflectors can be written for special usecases.
Let's look how to create a reflector. Remember that db4o relies on reflector to read the database, so errors in reflector may prevent your database from opening.
To keep things simple we will write a LoggingReflector, its only difference from standard reflector is that information about loaded classes is outputted to console. All reflectors used by db4o should implement com.db4o.reflect.Reflector interface.
01/* Copyright (C) 2004 - 2005 db4objects Inc. http://www.db4o.com */ 02
03
package com.db4odoc.f1.reflections; 04
05
import com.db4o.reflect.ReflectArray; 06
import com.db4o.reflect.ReflectClass; 07
import com.db4o.reflect.Reflector; 08
import com.db4o.reflect.jdk.JdkClass; 09
10
public class LoggingReflector implements Reflector { 11
private ReflectArray _array; 12
13
private Reflector _parent; 14
15
16
public LoggingReflector() { 17
18
} 19
20
public ReflectArray array() { 21
if(_array == null){ 22
_array = new LoggingArray(_parent); 23
} 24
return _array; 25
} 26
27
public boolean constructorCallsSupported() { 28
return true; 29
} 30
31
public ReflectClass forClass(Class clazz) { 32
ReflectClass rc = new JdkClass(_parent, clazz); 33
System.out.println("forClass: " + clazz+" -> "+(rc== null ? "" : rc.getName())); 34
return rc; 35
} 36
37
public ReflectClass forName(String className) { 38
try { 39
Class clazz = Class.forName(className); 40
ReflectClass rc = forClass(clazz); 41
System.out.println("forName: " + className+" -> "+(rc== null ? "" : rc.getName())); 42
return rc; 43
} catch (ClassNotFoundException e) { 44
return null; 45
} 46
} 47
48
public ReflectClass forObject(Object a_object) { 49
if (a_object == null) { 50
return null; 51
} 52
ReflectClass rc = _parent.forClass(a_object.getClass()); 53
System.out.println("forObject:" + a_object+" -> "+(rc== null ? "" : rc.getName())); 54
return rc; 55
} 56
57
public boolean isCollection(ReflectClass claxx) { 58
return false; 59
} 60
61
public void setParent(Reflector reflector) { 62
_parent = reflector; 63
} 64
65
public Object deepClone(Object context) { 66
return new LoggingReflector(); 67
} 68
}
It is easy to see that this reflector provides the same functionality as JdkReflector or NetReflector extended by console output. The following simple test will show how it works:
01public static void testReflector() 02
{ 03
LoggingReflector logger = new LoggingReflector(); 04
Db4o.configure().reflectWith(logger); 05
ObjectContainer db=Db4o.openFile(YAPFILENAME); 06
try { 07
ReflectClass rc = db.ext().reflector().forName(Car.class.getName()); 08
System.out.println("Reflected class: " + rc); 09
} finally { 10
db.close(); 11
} 12
}
The output can help you to track all the loaded classes.
Reflection is a powerful tool, which plays a fundamental role in db4o. Understanding reflection will help you to understand the whole db4o functionality in detail.