`
gordonAtJava
  • 浏览: 8033 次
文章分类
社区版块
存档分类
最新评论

一个用cglib和WeakHashMap做的lazyload原形实现

阅读更多
写于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里面,很简单滴
分享到:
评论

相关推荐

    cglib和asm

    ASM提供了底层的字节码操作能力,而CGlib则在其上构建了一个更易于使用的API,使得开发者无需直接与ASM的复杂接口打交道,就能实现类的动态扩展和代理。CGlib封装了ASM的一些细节,提供了更高级别的抽象,使得开发者...

    AOP-CGLIB学习-实现简单的注解权限系统

    标题中的"AOP-CGLIB学习-实现简单的注解权限系统"指的是使用Spring的面向切面编程(AOP)特性,结合CGLIB库来创建一个基于注解的权限控制系统。在这个系统中,通过CGLIB动态代理技术,可以对带有特定注解的方法进行...

    cglib包及依赖汉cglib3.1和asm4.2

    cglib包及依赖汉cglib3.1和asm4.2,主要作用是...JDK的动态代理用起来非常简单,但它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?现在我们可以使用CGLIB包

    CGLIB需要的asm-2.2.3.jar和cglib-nodep-2.2.jar

    CGLIB,全称为Code Generation Library,是一个强大的高性能的代码生成库,被广泛应用于Java世界,尤其是Spring框架中。它允许程序在运行时动态地创建Java对象并扩展已有类的功能。CGLIB是通过字节码技术实现的,而...

    cglib和asm jar包

    CGLIB全称为Code Generation Library,它是一个强大的高性能的代码生成库,主要用于扩展Java类与实现Java接口。当目标类不支持代理(如final类或没有接口的类)时,JDK的动态代理就无法工作,这时CGLIB就派上用场了...

    Cglib和asm的jar包

    在实际项目中,"cglib-2.2.jar"是Cglib的一个特定版本,包含了Cglib的类和接口,而"asm-3.3.1.jar"则是ASM的一个版本,提供了字节码操作的基础工具。当在项目中使用Cglib时,通常需要同时引入这两个库。

    cglib必须导入的包和案例

    JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现. Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的...

    基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)

    基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)...

    基于MAVEN项目的CGLib动态代理原理及实现

    CGLib是一个强大的、高性能的代码生成库,它可以在运行期扩展Java类与实现Java接口。它广泛用于许多AOP(面向切面编程)框架,如Spring AOP和dynaop,作为JDK动态代理的替代品,当目标类不支持接口时,CGLib能发挥重要...

    jdk与cglib动态代理与底层实现

    - **JDK代理**:JDK动态代理使用反射和InvocationHandler接口生成一个实现了目标接口的新类。在运行时,这个新类的实例作为代理对象,它的方法调用都会转发到InvocationHandler的`invoke()`方法。 - **CGLIB代理**...

    cglib.jar | asm.jar对应版本

    当一个类没有接口或者为了性能考虑不希望使用接口时,cglib就显得尤为重要。 cglib的核心类是`Enhancer`,它提供了创建代理对象的入口。通过调用`Enhancer.create()`方法,我们可以为指定的类创建一个代理对象,并...

    cglib2.2.jar

    CGLIB,全称为Code Generation Library,是一个非常强大的Java字节码操纵和动态代理框架。它在Java编程中扮演着重要角色,特别是在AOP(面向切面编程)和ORM(对象关系映射)框架中,如Spring AOP和Hibernate。这个...

    cglib及其依赖包

    在Spring框架中,CGLib被用作AOP代理的一个重要组件,特别是在没有实现接口的类上创建代理对象时,Spring会默认使用CGLib。 CGLib的工作原理是基于ASM库,ASM是一个字节码操作和分析框架,它可以用来动态生成类或...

    cglib.jar下载

    通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。 二、CGLIB原理 CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。...

    CGlib实现动态代理(承接上面JDK实现动态代理)

    在Java中,CGlib是一个非常重要的工具,特别是在AOP(面向切面编程)和ORM(对象关系映射)框架中,如Spring和Hibernate广泛使用它来实现代理功能。 CGlib动态代理的工作原理是通过继承被代理的目标类来创建子类,...

    一套匹配的cglib和asm的jar包。

    CGILib主要通过使用动态代理技术来实现,它可以在运行时创建一个类的子类,而无需获取其源代码或JDK的代理机制。在代理模式中,CGILib可以用来创建目标对象的代理,拦截并处理方法调用,实现如事务管理、日志记录等...

    CGLIB依赖jar包

    CGLIB是基于ASM(一个底层的Java字节码操作和分析框架)来实现的,它允许开发者在运行时为Java类创建子类,而无需访问其源代码或重新编译。这种技术在许多场景下都非常有用,比如实现AOP(面向切面编程)中的动态...

    简单实现Cglib子类代理

    Cglib子类代理是Java动态代理的一种实现方式,它主要通过字节码技术在运行时动态创建一个目标对象的子类,以此来实现代理功能。Cglib是一个强大的高性能的代码生成库,它在许多AOP(面向切面编程)框架中被广泛应用...

    java cglib和反射demo

    CGLib全称为Code Generation Library,是一个Java字节码操纵库,主要用于为类创建子类,从而实现动态代理。当目标类无法被继承(如final类)或者不希望修改源代码时,CGLib是一个很好的选择。它通过动态生成字节码...

Global site tag (gtag.js) - Google Analytics