自己参考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; } }