写于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里面,很简单滴
分享到:
相关推荐
ASM提供了底层的字节码操作能力,而CGlib则在其上构建了一个更易于使用的API,使得开发者无需直接与ASM的复杂接口打交道,就能实现类的动态扩展和代理。CGlib封装了ASM的一些细节,提供了更高级别的抽象,使得开发者...
标题中的"AOP-CGLIB学习-实现简单的注解权限系统"指的是使用Spring的面向切面编程(AOP)特性,结合CGLIB库来创建一个基于注解的权限控制系统。在这个系统中,通过CGLIB动态代理技术,可以对带有特定注解的方法进行...
cglib包及依赖汉cglib3.1和asm4.2,主要作用是...JDK的动态代理用起来非常简单,但它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?现在我们可以使用CGLIB包
CGLIB,全称为Code Generation Library,是一个强大的高性能的代码生成库,被广泛应用于Java世界,尤其是Spring框架中。它允许程序在运行时动态地创建Java对象并扩展已有类的功能。CGLIB是通过字节码技术实现的,而...
CGLIB全称为Code Generation Library,它是一个强大的高性能的代码生成库,主要用于扩展Java类与实现Java接口。当目标类不支持代理(如final类或没有接口的类)时,JDK的动态代理就无法工作,这时CGLIB就派上用场了...
在实际项目中,"cglib-2.2.jar"是Cglib的一个特定版本,包含了Cglib的类和接口,而"asm-3.3.1.jar"则是ASM的一个版本,提供了字节码操作的基础工具。当在项目中使用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是一个强大的、高性能的代码生成库,它可以在运行期扩展Java类与实现Java接口。它广泛用于许多AOP(面向切面编程)框架,如Spring AOP和dynaop,作为JDK动态代理的替代品,当目标类不支持接口时,CGLib能发挥重要...
- **JDK代理**:JDK动态代理使用反射和InvocationHandler接口生成一个实现了目标接口的新类。在运行时,这个新类的实例作为代理对象,它的方法调用都会转发到InvocationHandler的`invoke()`方法。 - **CGLIB代理**...
当一个类没有接口或者为了性能考虑不希望使用接口时,cglib就显得尤为重要。 cglib的核心类是`Enhancer`,它提供了创建代理对象的入口。通过调用`Enhancer.create()`方法,我们可以为指定的类创建一个代理对象,并...
CGLIB,全称为Code Generation Library,是一个非常强大的Java字节码操纵和动态代理框架。它在Java编程中扮演着重要角色,特别是在AOP(面向切面编程)和ORM(对象关系映射)框架中,如Spring AOP和Hibernate。这个...
在Spring框架中,CGLib被用作AOP代理的一个重要组件,特别是在没有实现接口的类上创建代理对象时,Spring会默认使用CGLib。 CGLib的工作原理是基于ASM库,ASM是一个字节码操作和分析框架,它可以用来动态生成类或...
通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。 二、CGLIB原理 CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。...
在Java中,CGlib是一个非常重要的工具,特别是在AOP(面向切面编程)和ORM(对象关系映射)框架中,如Spring和Hibernate广泛使用它来实现代理功能。 CGlib动态代理的工作原理是通过继承被代理的目标类来创建子类,...
CGILib主要通过使用动态代理技术来实现,它可以在运行时创建一个类的子类,而无需获取其源代码或JDK的代理机制。在代理模式中,CGILib可以用来创建目标对象的代理,拦截并处理方法调用,实现如事务管理、日志记录等...
CGLIB是基于ASM(一个底层的Java字节码操作和分析框架)来实现的,它允许开发者在运行时为Java类创建子类,而无需访问其源代码或重新编译。这种技术在许多场景下都非常有用,比如实现AOP(面向切面编程)中的动态...
Cglib子类代理是Java动态代理的一种实现方式,它主要通过字节码技术在运行时动态创建一个目标对象的子类,以此来实现代理功能。Cglib是一个强大的高性能的代码生成库,它在许多AOP(面向切面编程)框架中被广泛应用...
CGLib全称为Code Generation Library,是一个Java字节码操纵库,主要用于为类创建子类,从而实现动态代理。当目标类无法被继承(如final类)或者不希望修改源代码时,CGLib是一个很好的选择。它通过动态生成字节码...