自己参考hibernate的源代码,写了个大概能演示hibernate对对象熟悉延迟加载的几个类,用到了javassist 包。
调用的接口是这样的:
public class Test {
public static void main(String[] args) {
HibernateSeesion session = new HibernateSeesion();
Custerinform c1 = (Custerinform)session.load(Custerinform.class, "2");
//延迟加载对象上除了id以外的熟悉,无需连接数据库
System.out.println(c1.getId());
//正在需要用到其他熟悉时,再去数据库加载数据
System.out.println(c1.getFirstName());
//复用已经完全加载出来的对象,无需再连接数据库
System.out.println(c1.getLastName());
}
}
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class HibernateSeesion {
private static Map<String,Object> memDataBase = new HashMap<String,Object>(); //mock database
//一个标识接口,为每个被代理的对象都加上这个接口
private static Class<?>[] proxyInterfaces = {HibernateProxy.class};
//proxy工厂
private static Class<?> proxyFactory;
static{
Custerinform cust1 = new Custerinform();
cust1.setId("1");
cust1.setFirstName("张");
cust1.setLastName("阳");
Custerinform cust2 = new Custerinform();
cust2.setId("2");
cust2.setFirstName("张");
cust2.setLastName("梓琳");
memDataBase.put(Custerinform.class.getName() + cust1.getId(), cust1);
memDataBase.put(Custerinform.class.getName() + cust2.getId(), cust2);
//这里的写法,只是为了简单模拟一下hibernate的机制而已
proxyFactory = LazyInitializer.getProxyFactory(Custerinform.class,proxyInterfaces);
}
/**
* 返回proxy对象
* @param theClass
* @param id
* @return
*/
public Object load(Class<?> theClass, Serializable id){
return LazyInitializer.getProxy(proxyFactory, this, Custerinform.class.getName(),id);
}
/**
* 模拟从数据库中即使加载
* @param entityName
* @param id
* @return
*/
public Object immediateLoad(String entityName, Serializable id){
return memDataBase.get(entityName+id);
}
}
下面这个类是整个延迟加载的核心类容,
proxyfatory 和 proxy 都是在这里生成的,借助了 javassist 包提供的api。
import java.io.Serializable;
import java.lang.reflect.Method;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;
public class LazyInitializer implements MethodHandler {
private static final String INVOKE = "INVOKE";
private boolean constructed = false;
private boolean initialized = false;
private Serializable id;
private Object target;
private HibernateSeesion session;
private String entityName;
public LazyInitializer(final HibernateSeesion session, final String entityName, final Serializable id) {
this.id = id;
this.session = session;
this.entityName = entityName;
}
public static Class<?> getProxyFactory(final Class<?> persistentClass, Class<?>[] interfaces) {
try {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(persistentClass);
factory.setInterfaces(interfaces);
return factory.createClass();
} catch (Throwable t) {
throw new RuntimeException("Javassist Enhancement failed: " + persistentClass.getName(), t);
}
}
public static HibernateProxy getProxy(final Class<?> factory, final HibernateSeesion session,
final String entityName, final Serializable id) {
final LazyInitializer instance = new LazyInitializer(session, entityName, id);
HibernateProxy proxy;
try {
proxy = (HibernateProxy) factory.newInstance();
} catch (Exception e) {
throw new RuntimeException("Javassist Enhancement failed: " + entityName, e);
}
((ProxyObject) proxy).setHandler(instance);
instance.constructed = true;
return proxy;
}
@Override
public Object invoke(Object proxy, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (this.constructed) {
Object result;
final Object returnValue;
result = this.invoke(thisMethod, args, proxy); //判断被调用的方法是不是getId
if (result == INVOKE) {
Object target = getInvoke(); //获取目标对象
returnValue = thisMethod.invoke(target, args); //在目标对象上调用方法
return returnValue == target ? proxy : returnValue;
} else {
return result;
}
} else {
return proceed.invoke(proxy, args);
}
}
public final Serializable getIdentifier() {
return id;
}
public final void setIdentifier(Serializable id) {
this.id = id;
}
public final Object getInvoke() {
initialize();
return target;
}
/**
* 拦截 getId 方法,如果只是请求这个方法的话,无需从数据库中加载数据
*/
private final Object invoke(Method method, Object[] args, Object proxy) {
String methodName = method.getName();
int params = args.length;
if (params == 0) {
if (methodName.equals("getId")) {
return getIdentifier();
}
}
return INVOKE;
}
/**
* 初始化代理对象的目标对象
*/
private final void initialize() {
if (!initialized) {
System.out.println("load data from database");
target = session.immediateLoad(entityName, id);
initialized = true;
} else {
checkTargetState();
}
}
private void checkTargetState() {
if (target == null) {
System.out.println("找不到数据");
}
}
}
public interface HibernateProxy {
}
public class Custerinform {
private String id;
private String firstName;
private String lastName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}