Skip to content

Commit

Permalink
用简单的方式,实现简单的懒加载NutDao
Browse files Browse the repository at this point in the history
  • Loading branch information
wendal committed Apr 5, 2012
1 parent 4cccbb8 commit a6e1d49
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/org/nutz/dao/impl/EntityHolder.java
Expand Up @@ -26,7 +26,7 @@
public class EntityHolder {

// DaoSupport 会设置这个值
EntityMaker maker;
public EntityMaker maker;

private DaoSupport support;

Expand Down
7 changes: 5 additions & 2 deletions src/org/nutz/dao/impl/SimpleDataSource.java
Expand Up @@ -23,9 +23,12 @@ public class SimpleDataSource implements DataSource {
private String jdbcUrl;

public Connection getConnection() throws SQLException {
Connection conn;
if (username != null)
return DriverManager.getConnection(jdbcUrl, username, password);
return DriverManager.getConnection(jdbcUrl);
conn = DriverManager.getConnection(jdbcUrl, username, password);
else
conn = DriverManager.getConnection(jdbcUrl);
return conn;
}

public void close() {}
Expand Down
5 changes: 4 additions & 1 deletion src/org/nutz/dao/impl/entity/AnnotationEntityMaker.java
Expand Up @@ -75,7 +75,7 @@ public AnnotationEntityMaker(DataSource datasource, JdbcExpert expert, EntityHol
}

public <T> Entity<T> make(Class<T> type) {
NutEntity<T> en = new NutEntity<T>(type);
NutEntity<T> en = _createNutEntity(type);

TableInfo ti = _createTableInfo(type);

Expand Down Expand Up @@ -496,4 +496,7 @@ private void _checkupEntityFieldsWithDatabase(NutEntity<?> en) {
}
}

protected <T> NutEntity<T> _createNutEntity(Class<T> type) {
return new NutEntity<T>(type);
}
}
4 changes: 2 additions & 2 deletions src/org/nutz/dao/impl/entity/LinkFieldSet.java
Expand Up @@ -15,7 +15,7 @@
*
* @author zozoh(zozohtnt@gmail.com)
*/
class LinkFieldSet {
public class LinkFieldSet {

private ArrayList<LinkField> lnks;

Expand All @@ -30,7 +30,7 @@ void add(LinkField lnk) {
lnks.add(lnk);
}

List<LinkField> getAll() {
public List<LinkField> getAll() {
return lnks;
}

Expand Down
10 changes: 5 additions & 5 deletions src/org/nutz/dao/impl/entity/NutEntity.java
Expand Up @@ -71,17 +71,17 @@ public class NutEntity<T> implements Entity<T> {
/**
* 所有一对一映射字段
*/
private LinkFieldSet ones;
protected LinkFieldSet ones;

/**
* 所有一对多映射字段
*/
private LinkFieldSet manys;
protected LinkFieldSet manys;

/**
* 所有多对多映射字段
*/
private LinkFieldSet manymanys;
protected LinkFieldSet manymanys;

/**
* 数字型主键
Expand All @@ -96,7 +96,7 @@ public class NutEntity<T> implements Entity<T> {
/**
* 实体 Java 类型
*/
private Class<T> type;
protected Class<T> type;

/**
* 实体 Java 类型:通过 Mirror 增强
Expand All @@ -111,7 +111,7 @@ public class NutEntity<T> implements Entity<T> {
/**
* 根据默认构造函数或者工厂方法创建实体的方法
*/
private Borning<T> bornByDefault;
protected Borning<T> bornByDefault;

/**
* 实体表名
Expand Down
142 changes: 142 additions & 0 deletions src/org/nutz/dao/impl/ext/LazyAnnotationEntityMaker.java
@@ -0,0 +1,142 @@
package org.nutz.dao.impl.ext;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.nutz.aop.ClassAgent;
import org.nutz.aop.ClassDefiner;
import org.nutz.aop.DefaultClassDefiner;
import org.nutz.aop.InterceptorChain;
import org.nutz.aop.MethodInterceptor;
import org.nutz.aop.asm.AsmClassAgent;
import org.nutz.aop.matcher.MethodMatcherFactory;
import org.nutz.dao.Dao;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.LinkField;
import org.nutz.dao.impl.EntityHolder;
import org.nutz.dao.impl.entity.AnnotationEntityMaker;
import org.nutz.dao.impl.entity.NutEntity;
import org.nutz.dao.jdbc.JdbcExpert;
import org.nutz.ioc.aop.config.InterceptorPair;
import org.nutz.lang.Mirror;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

/**
* 支持简单的懒加载机制的AnnotationEntityMaker
* @author wendal(wendal1985@gmail.com)
*
*/
public class LazyAnnotationEntityMaker extends AnnotationEntityMaker {

private static final Log log = Logs.get();

private Dao dao;

private ClassDefiner cd;

public LazyAnnotationEntityMaker(DataSource datasource, JdbcExpert expert,
EntityHolder holder, Dao dao) {
super(datasource, expert, holder);
this.dao = dao;
cd = new DefaultClassDefiner(getClass().getClassLoader());
}

protected <T> NutEntity<T> _createNutEntity(Class<T> type) {
return new LazyNutEntity<T>(type);
}

@Override
public <T> Entity<T> make(Class<T> type) {
LazyNutEntity<T> en = (LazyNutEntity<T>) super.make(type);
en.init();
return en;
}

class LazyNutEntity<T> extends NutEntity<T>{

public LazyNutEntity(Class<T> type) {
super(type);
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public void init() {
//仅支持通过默认构造进行构建的类, TODO 支持Result方式生成对象的构造方法
if (this.bornByDefault != null) {
//检查是否需要进行Lazy处理
if (!ones.getAll().isEmpty() || !manys.getAll().isEmpty() || !manymanys.getAll().isEmpty()) {
if (log.isDebugEnabled())
log.debug("Found links , enable lazy!! -->" + type);
try {
Class klass = cd.load(type.getName() + ClassAgent.CLASSNAME_SUFFIX);
this.bornByDefault = Mirror.me(klass).getBorning();
return;
}
catch (ClassNotFoundException e) {}//事实上,这里肯定是ClassNotFound的

Mirror<T> mirror = Mirror.me(type);
List<InterceptorPair> interceptorPairs = new ArrayList<InterceptorPair>();
List<LinkField> lfs = new ArrayList<LinkField>();
lfs.addAll(ones.getAll());
lfs.addAll(manys.getAll());
lfs.addAll(manymanys.getAll());
//准备拦截器
for (LinkField lf : lfs) {
String fieldName = lf.getName();
try {
Method setter = mirror.getSetter(mirror.getField(fieldName));
LazyMethodInterceptor lmi = new LazyMethodInterceptor(setter, fieldName);
interceptorPairs.add(new InterceptorPair(lmi, MethodMatcherFactory.matcher("^(get|set)"+Strings.capitalize(fieldName)+"$")));
} catch (Throwable e) {
if (log.isWarnEnabled())
log.warn("Not setter found for LazyLoading ?!", e);
}
}
//生成Aop化的类
ClassAgent agent = new AsmClassAgent();
for (InterceptorPair interceptorPair : interceptorPairs)
agent.addInterceptor( interceptorPair.getMethodMatcher(),
interceptorPair.getMethodInterceptor());
Class lazyClass = agent.define(cd, type);
this.bornByDefault = Mirror.me(lazyClass).getBorning();
}
}
}
}

class LazyMethodInterceptor implements MethodInterceptor {

private LazyStatus status = LazyStatus.CAN_FETCH;

private Method setter;
private String fieldName;

public LazyMethodInterceptor(Method setter, String fieldName) {
this.setter = setter;
this.fieldName = fieldName;
}


public void filter(InterceptorChain chain) throws Throwable {
if (status == LazyStatus.CAN_FETCH) {
if (chain.getCallingMethod() != setter) {
dao.fetchLinks(chain.getCallingObj(), fieldName);//这里会触发setter被调用
status = LazyStatus.FETCHED;
} else
status = LazyStatus.NO_NEED; //如果setter被调用,那么也就不再需要懒加载了
}
chain.doChain();
}

}

enum LazyStatus {
CAN_FETCH,
FETCHED,
NO_NEED
}
}
47 changes: 47 additions & 0 deletions src/org/nutz/dao/impl/ext/LazyNutDao.java
@@ -0,0 +1,47 @@
package org.nutz.dao.impl.ext;

import javax.sql.DataSource;

import org.nutz.aop.AopCallback;
import org.nutz.dao.SqlManager;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.EntityMaker;
import org.nutz.dao.impl.EntityHolder;
import org.nutz.dao.impl.NutDao;

/**
* 支持简单的懒加载机制的NutDao
* @author wendal(wendal1985@gmail.com)
*
*/
public class LazyNutDao extends NutDao {

public void setDataSource(DataSource ds) {
super.setDataSource(ds);
this.holder = new EntityHolder(this) {
@SuppressWarnings("unchecked")
public <T> Entity<T> getEntity(Class<T> classOfT) {
if (AopCallback.class.isAssignableFrom(classOfT))
return (Entity<T>) getEntity(classOfT.getSuperclass());
return super.getEntity(classOfT);
}
};
this.holder.maker = createEntityMaker();
}

protected EntityMaker createEntityMaker() {
return new LazyAnnotationEntityMaker(dataSource, expert, holder, this);
}

public LazyNutDao() {
super();
}

public LazyNutDao(DataSource dataSource) {
super(dataSource);
}

public LazyNutDao(DataSource dataSource, SqlManager sqlManager) {
super(dataSource, sqlManager);
}
}

0 comments on commit a6e1d49

Please sign in to comment.