一、延遲加載器LazyLoader作用:
說到延遲加載,應該經常接觸到,尤其是使用Hibernate的時候,本篇將通過一個實例分析延遲加載的實現方式。LazyLoader接口繼承了Callback,因此也算是CGLib中的一種Callback類型。
二、示例:
首先定義一個實體類LoaderBean,該Bean內有一個需要延遲加載的屬性對象PropertyBean。
LoaderBean.java:
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:
public class PropertyBean { private String propertyName; private int propertyValue; //setter/getter }
在LoaderBean的構造方法中,對屬性Bean進行了代理類生成,使用了CGLib中的LazyLoader回調接口。
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; } }
驗證延遲加載
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());
控制台輸出
loaderNameA 123 LazyLoader loadObject() ... lazy-load object propertyName! 11 after... lazy-load object propertyName!
注意,第一次獲取property bean的屬性時,會觸發代理類回調方法。第二次再獲取property bean的屬性時,就直接返回屬性值而不會再次觸發代理類回調方法了。
可見,延遲加載原理:對需要延遲加載的對象添加代理,在獲取該對象屬性時先通過代理類回調方法進行對象初始化。在不需要加載該對象時,只要不去獲取該對象內屬性,該對象就不會被初始化了(在CGLib的實現中只要去訪問該對象內屬性的getter方法,就會自動觸發代理類回調)。