写于3月份,耗时2小时,时间仓促肯定很多不周全,所以说是个初步原形
上代码


LazyLoadMethodInterceptor.java
其中session是一个persistence layer的session mockup,这个intercepter是用来对pojo的get方法做监听

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);
	}
}





LazyLoadHelper.java
一个weakhashmap的singleton包装
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;
	}

}


Session.java
从数据库里面load对象的时候,如果该对象的某个属性是个bean就不load这个属性,直接把属性对应的id和属性的名字保存在weakhashmap里面,当该对象的get属性方法被调用时候才weakhashmap里面读取id,实行lazyload
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);
	}
}



Client.java
一个测试用的client
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());
	}
}



其实就是用cglib监听每个pojo的get方法,所有的pojo都在从数据库中load时候做了cglib包装,当pojo属性需要被lazyload时候就把相关信息放到一个weakhashmap里面,很简单滴
评论
发表评论

您还没有登录,请登录后发表评论

gordon@java
搜索本博客
博客分类
最近加入圈子
最新评论