写于3月份,耗时2小时,时间仓促肯定很多不周全,所以说是个初步原形
上代码
LazyLoadMethodInterceptor.java
其中session是一个persistence layer的session mockup,这个intercepter是用来对pojo的get方法做监听
[code]
package com.gordon.lazyload.aop;
import java.lang.reflect.Method;
import java.util.Map;
import com.gordon.lazyload.persistence.Session;
import com.gordon.lazyload.utils.ClassHelper;
import com.gordon.lazyload.utils.LazyLoadHelper;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* @author hugo
* @date 2007-3-7 0:34:23 LazyLoadMethodInterceptor
*/
public class LazyLoadMethodInterceptor implements MethodInterceptor {
/**
*
*/
public LazyLoadMethodInterceptor() {
super();
// TODO Auto-generated constructor stub
}
private Object target;
public void setTarget(Object target) {
this.target = target;
}
/*
* (non-Javadoc)
*
* @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[],
* net.sf.cglib.proxy.MethodProxy)
*/
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
ClassHelper h = ClassHelper.getInstance();
Map<Object, Map<String, String>> lazyMap = LazyLoadHelper.getInstance().getLazyMap();
if (method.getName().substring(0, 3).equals("get") && !h.isPrimative(method.getReturnType())
&& lazyMap.containsKey(target)) {
// System.out.println(target.getClass().getName()+"."+method.getName()+" has been called");
String fieldName = method.getName().substring(3).toLowerCase();
Map<String, String> propertyMap = lazyMap.get(target);
if (propertyMap.containsKey(fieldName)) {
String id = propertyMap.get(fieldName);
System.out.println(target + " lazy loading [property:" + fieldName + ",id:" + id + "]");
Session s = new Session();
Object propertyValue = s.loadObjectById(method.getReturnType(), id);
Method m = target.getClass().getMethod("set" + method.getName().substring(3), method.getReturnType());
m.invoke(target, propertyValue);
lazyMap.get(target).remove(fieldName);
if (lazyMap.get(target).isEmpty()) lazyMap.remove(target);
return propertyValue;
}
}
return method.invoke(target, args);
}
}
[/code]
LazyLoadHelper.java
一个weakhashmap的singleton包装
[code]
package com.gordon.lazyload.utils;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
/**
* @author hugo
* @date 2007-3-7 2:30:22
* LazyLoadHelper
*/
public class LazyLoadHelper {
/**
*
*/
private LazyLoadHelper() {
super();
lazyMap=Collections.synchronizedMap(new WeakHashMap<Object,Map<String,String>>());
// TODO Auto-generated constructor stub
}
public static LazyLoadHelper getInstance() {
if(llh==null)llh=new LazyLoadHelper();
return llh;
}
private Map<Object,Map<String,String>> lazyMap;
private static LazyLoadHelper llh=null;
public Map<Object, Map<String,String>> getLazyMap() {
return lazyMap;
}
}
[/code]
Session.java
从数据库里面load对象的时候,如果该对象的某个属性是个bean就不load这个属性,直接把属性对应的id和属性的名字保存在weakhashmap里面,当该对象的get属性方法被调用时候才weakhashmap里面读取id,实行lazyload
[code]
package com.gordon.lazyload.persistence;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import com.gordon.lazyload.aop.LazyLoadMethodInterceptor;
import com.gordon.lazyload.utils.ClassHelper;
import com.gordon.lazyload.utils.LazyLoadHelper;
import net.sf.cglib.proxy.Enhancer;
/**
* @author hugo
* @date 2007-3-7 0:18:38
* Session
*/
public class Session {
/**
*
*/
public Session() {
super();
// TODO Auto-generated constructor stub
}
public<E> E loadObjectById(Class<E> cls,String id) throws Throwable {
E obj=cls.newInstance();
ClassHelper h=ClassHelper.getInstance();
//using java.beans.PropertyDescriptor
/*
PropertyDescriptor[] properties=Introspector.getBeanInfo(cls).getPropertyDescriptors();
for(PropertyDescriptor p:properties) {
if(p.getPropertyType().equals(Class.class)) continue;
if(h.isPrimative(p.getPropertyType())) {
p.getWriteMethod().invoke(obj, h.getMockValue(p.getPropertyType()));
}else {
Map<String,String> propertyMap=LazyLoadHelper.getInstance().getLazyMap().get(obj);
if(propertyMap==null) {
propertyMap=new HashMap<String,String>();
LazyLoadHelper.getInstance().getLazyMap().put(obj, propertyMap);
}
propertyMap.put(p.getName(), new String((String)h.getMockValue(String.class)));
}
}
*/
//using java.lang.reflect.Field
for(Field f:cls.getDeclaredFields()) {
if(h.isPrimative(f.getType())) {
Method m=cls.getMethod(this.setter(f.getName()), f.getType());
m.invoke(obj, h.getMockValue(f.getType(),f.getName()));
}else {
Map<String,String> propertyMap=LazyLoadHelper.getInstance().getLazyMap().get(obj);
if(propertyMap==null) {
propertyMap=new HashMap<String,String>();
LazyLoadHelper.getInstance().getLazyMap().put(obj, propertyMap);
}
//这里把一个是pojo的property的名字和id放到weakhashmap里面
propertyMap.put(f.getName(), new String((String)h.getMockValue(String.class,f.getName())));
}
}
obj=(E)getWrappedInstance(obj);
return obj;
}
private Object getWrappedInstance(Object obj) {
Object result=null;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(obj.getClass());
LazyLoadMethodInterceptor mi=new LazyLoadMethodInterceptor();
mi.setTarget(obj);
enhancer.setCallback(mi);
result=enhancer.create();
return result;
}
private String capitalize(String str) {
return str.substring(0,1).toUpperCase()+str.substring(1);
}
/*
private String getter(String str) {
return "get"+this.capitalize(str);
}
*/
private String setter(String str) {
return "set"+this.capitalize(str);
}
}
[/code]
Client.java
一个测试用的client
[code]
package com.gordon.lazy.test;
import com.gordon.lazyload.domain.Nonsense2;
import com.gordon.lazyload.domain.User;
import com.gordon.lazyload.persistence.Session;
import com.gordon.lazyload.utils.LazyLoadHelper;
/**
* @author hugo
* @date 2007-3-7 1:11:53
* Client
*/
public class Client {
/**
*
*/
public Client() {
super();
// TODO Auto-generated constructor stub
}
public void runMe() {
Session s=new Session();
try {
User u=s.loadObjectById(User.class, "1");
u.getAccount();
u.getAccount();
u.getEmail().getContent();
u.getEmail().getContent();
User u2=s.loadObjectById(User.class, "2");
u2.getAge();
u2.getAlive();
u2.getWealth();
u2.getAccount();
u2.getAccount();
u2.getEmail().getContent();
u2.getEmail().getContent();
Nonsense2 n=s.loadObjectById(Nonsense2.class, "2");
System.out.println(n.getName());
System.out.println(n.getN().getText());
System.out.println(LazyLoadHelper.getInstance().getLazyMap().keySet().size());
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Client c=new Client();
c.runMe();
System.gc();
System.out.println(LazyLoadHelper.getInstance().getLazyMap().keySet().size());
}
}
[/code]
其实就是用cglib监听每个pojo的get方法,所有的pojo都在从数据库中load时候做了cglib包装,当pojo属性需要被lazyload时候就把相关信息放到一个weakhashmap里面,很简单滴
上代码
LazyLoadMethodInterceptor.java
其中session是一个persistence layer的session mockup,这个intercepter是用来对pojo的get方法做监听
[code]
package com.gordon.lazyload.aop;
import java.lang.reflect.Method;
import java.util.Map;
import com.gordon.lazyload.persistence.Session;
import com.gordon.lazyload.utils.ClassHelper;
import com.gordon.lazyload.utils.LazyLoadHelper;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* @author hugo
* @date 2007-3-7 0:34:23 LazyLoadMethodInterceptor
*/
public class LazyLoadMethodInterceptor implements MethodInterceptor {
/**
*
*/
public LazyLoadMethodInterceptor() {
super();
// TODO Auto-generated constructor stub
}
private Object target;
public void setTarget(Object target) {
this.target = target;
}
/*
* (non-Javadoc)
*
* @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[],
* net.sf.cglib.proxy.MethodProxy)
*/
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
ClassHelper h = ClassHelper.getInstance();
Map<Object, Map<String, String>> lazyMap = LazyLoadHelper.getInstance().getLazyMap();
if (method.getName().substring(0, 3).equals("get") && !h.isPrimative(method.getReturnType())
&& lazyMap.containsKey(target)) {
// System.out.println(target.getClass().getName()+"."+method.getName()+" has been called");
String fieldName = method.getName().substring(3).toLowerCase();
Map<String, String> propertyMap = lazyMap.get(target);
if (propertyMap.containsKey(fieldName)) {
String id = propertyMap.get(fieldName);
System.out.println(target + " lazy loading [property:" + fieldName + ",id:" + id + "]");
Session s = new Session();
Object propertyValue = s.loadObjectById(method.getReturnType(), id);
Method m = target.getClass().getMethod("set" + method.getName().substring(3), method.getReturnType());
m.invoke(target, propertyValue);
lazyMap.get(target).remove(fieldName);
if (lazyMap.get(target).isEmpty()) lazyMap.remove(target);
return propertyValue;
}
}
return method.invoke(target, args);
}
}
[/code]
LazyLoadHelper.java
一个weakhashmap的singleton包装
[code]
package com.gordon.lazyload.utils;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
/**
* @author hugo
* @date 2007-3-7 2:30:22
* LazyLoadHelper
*/
public class LazyLoadHelper {
/**
*
*/
private LazyLoadHelper() {
super();
lazyMap=Collections.synchronizedMap(new WeakHashMap<Object,Map<String,String>>());
// TODO Auto-generated constructor stub
}
public static LazyLoadHelper getInstance() {
if(llh==null)llh=new LazyLoadHelper();
return llh;
}
private Map<Object,Map<String,String>> lazyMap;
private static LazyLoadHelper llh=null;
public Map<Object, Map<String,String>> getLazyMap() {
return lazyMap;
}
}
[/code]
Session.java
从数据库里面load对象的时候,如果该对象的某个属性是个bean就不load这个属性,直接把属性对应的id和属性的名字保存在weakhashmap里面,当该对象的get属性方法被调用时候才weakhashmap里面读取id,实行lazyload
[code]
package com.gordon.lazyload.persistence;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import com.gordon.lazyload.aop.LazyLoadMethodInterceptor;
import com.gordon.lazyload.utils.ClassHelper;
import com.gordon.lazyload.utils.LazyLoadHelper;
import net.sf.cglib.proxy.Enhancer;
/**
* @author hugo
* @date 2007-3-7 0:18:38
* Session
*/
public class Session {
/**
*
*/
public Session() {
super();
// TODO Auto-generated constructor stub
}
public<E> E loadObjectById(Class<E> cls,String id) throws Throwable {
E obj=cls.newInstance();
ClassHelper h=ClassHelper.getInstance();
//using java.beans.PropertyDescriptor
/*
PropertyDescriptor[] properties=Introspector.getBeanInfo(cls).getPropertyDescriptors();
for(PropertyDescriptor p:properties) {
if(p.getPropertyType().equals(Class.class)) continue;
if(h.isPrimative(p.getPropertyType())) {
p.getWriteMethod().invoke(obj, h.getMockValue(p.getPropertyType()));
}else {
Map<String,String> propertyMap=LazyLoadHelper.getInstance().getLazyMap().get(obj);
if(propertyMap==null) {
propertyMap=new HashMap<String,String>();
LazyLoadHelper.getInstance().getLazyMap().put(obj, propertyMap);
}
propertyMap.put(p.getName(), new String((String)h.getMockValue(String.class)));
}
}
*/
//using java.lang.reflect.Field
for(Field f:cls.getDeclaredFields()) {
if(h.isPrimative(f.getType())) {
Method m=cls.getMethod(this.setter(f.getName()), f.getType());
m.invoke(obj, h.getMockValue(f.getType(),f.getName()));
}else {
Map<String,String> propertyMap=LazyLoadHelper.getInstance().getLazyMap().get(obj);
if(propertyMap==null) {
propertyMap=new HashMap<String,String>();
LazyLoadHelper.getInstance().getLazyMap().put(obj, propertyMap);
}
//这里把一个是pojo的property的名字和id放到weakhashmap里面
propertyMap.put(f.getName(), new String((String)h.getMockValue(String.class,f.getName())));
}
}
obj=(E)getWrappedInstance(obj);
return obj;
}
private Object getWrappedInstance(Object obj) {
Object result=null;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(obj.getClass());
LazyLoadMethodInterceptor mi=new LazyLoadMethodInterceptor();
mi.setTarget(obj);
enhancer.setCallback(mi);
result=enhancer.create();
return result;
}
private String capitalize(String str) {
return str.substring(0,1).toUpperCase()+str.substring(1);
}
/*
private String getter(String str) {
return "get"+this.capitalize(str);
}
*/
private String setter(String str) {
return "set"+this.capitalize(str);
}
}
[/code]
Client.java
一个测试用的client
[code]
package com.gordon.lazy.test;
import com.gordon.lazyload.domain.Nonsense2;
import com.gordon.lazyload.domain.User;
import com.gordon.lazyload.persistence.Session;
import com.gordon.lazyload.utils.LazyLoadHelper;
/**
* @author hugo
* @date 2007-3-7 1:11:53
* Client
*/
public class Client {
/**
*
*/
public Client() {
super();
// TODO Auto-generated constructor stub
}
public void runMe() {
Session s=new Session();
try {
User u=s.loadObjectById(User.class, "1");
u.getAccount();
u.getAccount();
u.getEmail().getContent();
u.getEmail().getContent();
User u2=s.loadObjectById(User.class, "2");
u2.getAge();
u2.getAlive();
u2.getWealth();
u2.getAccount();
u2.getAccount();
u2.getEmail().getContent();
u2.getEmail().getContent();
Nonsense2 n=s.loadObjectById(Nonsense2.class, "2");
System.out.println(n.getName());
System.out.println(n.getN().getText());
System.out.println(LazyLoadHelper.getInstance().getLazyMap().keySet().size());
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Client c=new Client();
c.runMe();
System.gc();
System.out.println(LazyLoadHelper.getInstance().getLazyMap().keySet().size());
}
}
[/code]
其实就是用cglib监听每个pojo的get方法,所有的pojo都在从数据库中load时候做了cglib包装,当pojo属性需要被lazyload时候就把相关信息放到一个weakhashmap里面,很简单滴