实战CGLib系列之proxy篇(三):延迟加载LazyLoader

作者shensy及出处http://shensy.iteye.com/blog/1881277

实战CGLib系列文章
本篇介绍延迟加载器LazyLoader。
一、作用:
说到延迟加载,应该经常接触到,尤其是使用Hibernate的时候,本篇将通过一个实例分析延迟加载的实现方式。
LazyLoader接口继承了Callback,因此也算是CGLib中的一种Callback类型。

二、示例:
首先定义一个实体类LoaderBean,该Bean内有一个需要延迟加载的属性PropertyBean。

LoaderBean.java:

Java代码 复制代码  收藏代码
  1. public class LoaderBean {   
  2.     private String loaderName;   
  3.     private int loaderValue;   
  4.     private PropertyBean propertyBean;   
  5.     public LoaderBean(){   
  6.         this.loaderName="loaderNameA";   
  7.         this.loaderValue=123;   
  8.         this.propertyBean=createPropertyBean();   
  9.     }   
  10.     protected PropertyBean createPropertyBean(){   
  11.         Enhancer enhancer=new Enhancer();   
  12.         enhancer.setSuperclass(PropertyBean.class);   
  13.         return (PropertyBean)enhancer.create(PropertyBean.class,new ConcreteClassLazyLoader());   
  14.     }   
  15.        
  16.     //setter/getter...   
  17. }  
public class LoaderBean {
	private String loaderName;
	private int loaderValue;
	private PropertyBean propertyBean;
	public LoaderBean(){
		this.loaderName="loaderNameA";
		this.loaderValue=123;
		this.propertyBean=createPropertyBean();
	}
	protected PropertyBean createPropertyBean(){
		Enhancer enhancer=new Enhancer();
		enhancer.setSuperclass(PropertyBean.class);
		return (PropertyBean)enhancer.create(PropertyBean.class,new ConcreteClassLazyLoader());
	}
	
	//setter/getter...
}

PropertyBean.java:

Java代码 复制代码  收藏代码
  1. public class PropertyBean {   
  2.     private String propertyName;   
  3.     private int propertyValue;   
  4.        
  5.     //setter/getter   
  6. }  
public class PropertyBean {
	private String propertyName;
	private int propertyValue;
	
	//setter/getter
}

在LoaderBean的构造方法中,对属性Bean进行了代理类生成,使用了CGLib中的LazyLoader回调接口。

Java代码 复制代码  收藏代码
  1. public class ConcreteClassLazyLoader implements LazyLoader{   
  2.     public Object loadObject() throws Exception {   
  3.         System.out.println("LazyLoader loadObject() ...");   
  4.         PropertyBean bean=new PropertyBean();   
  5.         bean.setPropertyName("lazy-load object propertyName!");   
  6.         bean.setPropertyValue(11);   
  7.         return bean;   
  8.     }   
  9. }  
public class ConcreteClassLazyLoader implements LazyLoader{
	public Object loadObject() throws Exception {
		System.out.println("LazyLoader loadObject() ...");
		PropertyBean bean=new PropertyBean();
		bean.setPropertyName("lazy-load object propertyName!");
		bean.setPropertyValue(11);
		return bean;
	}
}

验证延迟加载:

Java代码 复制代码  收藏代码
  1. LoaderBean loader=new LoaderBean();   
  2. System.out.println(loader.getLoaderName());   
  3. System.out.println(loader.getLoaderValue());   
  4. PropertyBean propertyBean=loader.getPropertyBean();//访问延迟加载对象   
  5. System.out.println(propertyBean.getPropertyName());   
  6. System.out.println(propertyBean.getPropertyValue());   
  7. System.out.println("after...");   
  8. //当再次访问延迟加载对象时,就不会再执行回调了   
  9. System.out.println(propertyBean.getPropertyName());  
LoaderBean loader=new LoaderBean();
System.out.println(loader.getLoaderName());
System.out.println(loader.getLoaderValue());
PropertyBean propertyBean=loader.getPropertyBean();//访问延迟加载对象
System.out.println(propertyBean.getPropertyName());
System.out.println(propertyBean.getPropertyValue());
System.out.println("after...");
//当再次访问延迟加载对象时,就不会再执行回调了
System.out.println(propertyBean.getPropertyName());

 控制台输出:

控制台代码 复制代码  收藏代码
  1. loaderNameA   
  2. 123  
  3. LazyLoader loadObject() ...   
  4. lazy-load object propertyName!   
  5. 11  
  6. after...   
  7. lazy-load object propertyName!  
loaderNameA
123
LazyLoader loadObject() ...
lazy-load object propertyName!
11
after...
lazy-load object propertyName!

注意,第一次获取property bean的属性时,会触发代理类回调方法。第二次再获取property bean的属性时,就直接返回属性值而不会再次触发代理类回调方法了。

可见,延迟加载原理:

对需要延迟加载的对象添加代理,在获取该对象属性时先通过代理类回调方法进行对象初始化。

在不需要加载该对象时,只要不去获取该对象内属性,该对象就不会被初始化了(在CGLib的实现中只要去访问该对象内属性的getter方法,就会自动触发代理类回调)。

 

你可能感兴趣的:(实战CGLib系列之proxy篇(三):延迟加载LazyLoader)