hibernate的lazy懒加载:
只有我们在正真使用时,它才会发出SQL语句,给我们去查询,如果不使用对象则不会发SQL语句进行查询。
Hibernate中lazy(懒加载)的实现:
采用了第三方组件的库,这个库叫cglib.jar(比较流行),这个库对我们的类生成代理类(JDK的动态代理,只能对JDK中实现了接口的类进行代理),代理可以控制源对象并且可以对源对象的功能进行增强,而cglib.jar可以对类进行代理(cglib对我们的类进行继承,生成一个子类,这个子类作为代理类返回给你)。
只有你正真代理类的方法,则会查看你有没有加载目标对象,如果没有则会加载目标对象。
可是网上很少有文章描述java bean如何实现懒加载。
下面,我使用cglib实现java bean 的懒加载方式。
1、首先,创建一个User类, 有name、age、car字段,而car字段是大对象, 这时候可以让car字段以懒加载方式加载数据。
public class User {
private String name;
private int age;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
}
public class Car {
private String carName;
private String type;
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
2、利用cglib,创建懒加载工厂类LazyloadFactory, 实现cglib 的MethodInterceptor接口
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class LazyloadFactory implements MethodInterceptor {
private Object target;
public LazyloadFactory(Object target) {
this.target = target;
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
String methodName = method.getName();
if (methodName.startsWith("get")) {
//获取属性
Field field = target.getClass().getDeclaredField(
methodName.substring(3, methodName.length()).toLowerCase());
//对大字段懒加载
if(field.getType()== Car.class) {
field.setAccessible(true);
//打印要执行的方法
System.out.println("懒加载------>执行" + method.getName());
//延迟加载, 这里可以从数据库中获取数据,给属性赋值
System.out.println("懒加载------>" + "加载大对象开始");
Thread.sleep(1000);
Car car = new Car();
car.setCarName("京Q123456");
car.setType("宝马");
//给指定的属性赋值
field.set(target, car);
System.out.println("懒加载------>" + "加载大对象完成");
}
}
Object result = proxy.invoke(target, args);
return result;
}
}
3、创建获取User的Service, 这样可以实现懒加载
import org.springframework.cglib.proxy.Enhancer;
public class UserService {
public User getUser() {
User user = new User();
//先给其他字段赋值
user.setName("suncht");
user.setAge(20);
//再给大字段赋值(懒加载)
LazyloadFactory intercepter=new LazyloadFactory(user);
return (User) Enhancer.create(User.class,intercepter);
}
}
4、我们用测试类进行测试下, 运行时,很明显会感觉到getCar().getName()进行懒加载
public class Test {
public static void main(String[] args) {
UserService service = new UserService();
User user = service.getUser();
System.out.println(user.getName());
System.out.println(user.getAge());
System.out.println(user.getCar().getCarName());
}
}
结果如下:
suncht
20
懒加载------>执行getCar
懒加载------>加载大对象开始
懒加载------>加载大对象完成
京Q123456