org.jfaster.mango.operator.Mango Maven / Gradle / Ivy
/*
* Copyright 2014 mango.jfaster.org
*
* The Mango Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jfaster.mango.operator;
import org.jfaster.mango.annotation.Cache;
import org.jfaster.mango.annotation.DB;
import org.jfaster.mango.datasource.DataSourceFactory;
import org.jfaster.mango.datasource.DataSourceFactoryGroup;
import org.jfaster.mango.datasource.SimpleDataSourceFactory;
import org.jfaster.mango.descriptor.MethodDescriptor;
import org.jfaster.mango.descriptor.Methods;
import org.jfaster.mango.exception.InitializationException;
import org.jfaster.mango.interceptor.Interceptor;
import org.jfaster.mango.interceptor.InterceptorChain;
import org.jfaster.mango.operator.cache.CacheHandler;
import org.jfaster.mango.stat.*;
import org.jfaster.mango.util.ToStringHelper;
import org.jfaster.mango.util.local.CacheLoader;
import org.jfaster.mango.util.local.DoubleCheckCache;
import org.jfaster.mango.util.local.LoadingCache;
import org.jfaster.mango.util.logging.InternalLogger;
import org.jfaster.mango.util.logging.InternalLoggerFactory;
import org.jfaster.mango.util.reflect.AbstractInvocationHandler;
import org.jfaster.mango.util.reflect.Reflection;
import javax.sql.DataSource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* mango框架DAO工厂
*
* @author ash
*/
public class Mango extends Config {
private final static InternalLogger logger = InternalLoggerFactory.getInstance(Mango.class);
/**
* 数据源工厂组
*/
private DataSourceFactoryGroup dataSourceFactoryGroup;
/**
* 缓存处理器
*/
private CacheHandler cacheHandler;
/**
* 是否懒加载
*/
private boolean isLazyInit = false;
/**
* 拦截器链,默认为空
*/
private InterceptorChain interceptorChain = new InterceptorChain();
/**
* 统计收集器
*/
private final StatCollector statCollector = new StatCollector();
/**
* mango实例
*/
private final static CopyOnWriteArrayList instances = new CopyOnWriteArrayList();
private Mango() {
}
public synchronized static Mango newInstance() {
if (instances.size() == 1) {
if (logger.isWarnEnabled()) {
logger.warn("Find out more mango instances, it is recommended to use only one");
}
}
Mango mango = new Mango();
instances.add(mango);
return mango;
}
public static Mango newInstance(DataSource dataSource) {
Mango mango = newInstance();
mango.setDataSource(dataSource);
return mango;
}
public static Mango newInstance(DataSourceFactory dataSourceFactory) {
Mango mango = newInstance();
mango.setDataSourceFactory(dataSourceFactory);
return mango;
}
public static Mango newInstance(DataSourceFactory... dataSourceFactories) {
return newInstance(Arrays.asList(dataSourceFactories));
}
public static Mango newInstance(List dataSourceFactories) {
Mango mango = newInstance();
mango.setDataSourceFactories(dataSourceFactories);
return mango;
}
public static Mango newInstance(DataSourceFactory dataSourceFactory, CacheHandler cacheHandler) {
Mango mango = newInstance();
mango.setDataSourceFactory(dataSourceFactory);
mango.setCacheHandler(cacheHandler);
return mango;
}
public static Mango newInstance(List dataSourceFactories, CacheHandler cacheHandler) {
Mango mango = newInstance();
mango.setDataSourceFactories(dataSourceFactories);
mango.setCacheHandler(cacheHandler);
return mango;
}
/**
* 获得mango实例
*/
public static List getInstances() {
List mangos = new ArrayList();
for (Mango instance : instances) {
mangos.add(instance);
}
return Collections.unmodifiableList(mangos);
}
/**
* 添加拦截器
*/
public void addInterceptor(Interceptor interceptor) {
if (interceptor == null) {
throw new NullPointerException("interceptor can't be null");
}
if (interceptorChain == null) {
interceptorChain = new InterceptorChain();
}
interceptorChain.addInterceptor(interceptor);
}
/**
* 创建代理DAO类
*/
public T create(Class daoClass) {
if (daoClass == null) {
throw new NullPointerException("dao interface can't be null");
}
if (!daoClass.isInterface()) {
throw new IllegalArgumentException("expected an interface to proxy, but " + daoClass);
}
DB dbAnno = daoClass.getAnnotation(DB.class);
if (dbAnno == null) {
throw new IllegalStateException("dao interface expected one @DB " +
"annotation but not found");
}
Cache cacheAnno = daoClass.getAnnotation(Cache.class);
if (cacheAnno != null && cacheHandler == null) {
throw new IllegalStateException("if @Cache annotation on dao interface, " +
"cacheHandler can't be null");
}
if (dataSourceFactoryGroup == null) {
throw new IllegalArgumentException("please set dataSource or dataSourceFactory or dataSourceFactories");
}
MangoInvocationHandler handler = new MangoInvocationHandler(
daoClass, dataSourceFactoryGroup, cacheHandler, interceptorChain, statCollector, this);
if (!isLazyInit) { // 不使用懒加载,则提前加载
List methods = Methods.listMethods(daoClass);
for (Method method : methods) {
try {
handler.getOperator(method);
} catch (Throwable e) {
throw new InitializationException("initialize " + ToStringHelper.toString(method) + " error", e);
}
}
}
return Reflection.newProxy(daoClass, handler);
}
/**
* 返回状态信息
*/
public StatInfo getStatInfo() {
return statCollector.getStatInfo();
}
/**
* 根据数据源工厂名字获得主库数据源
*/
public DataSource getMasterDataSource(String name) {
return dataSourceFactoryGroup.getMasterDataSource(name);
}
public void setDataSource(DataSource dataSource) {
if (dataSource == null) {
throw new NullPointerException("dataSource can't be null");
}
setDataSourceFactory(new SimpleDataSourceFactory(dataSource));
}
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
if (dataSourceFactory == null) {
throw new NullPointerException("dataSourceFactory can't be null");
}
setDataSourceFactories(Arrays.asList(dataSourceFactory));
}
public void addDataSourceFactory(DataSourceFactory dataSourceFactory) {
if (dataSourceFactory == null) {
throw new NullPointerException("dataSourceFactory can't be null");
}
if (dataSourceFactoryGroup == null) {
dataSourceFactoryGroup = new DataSourceFactoryGroup();
}
dataSourceFactoryGroup.addDataSourceFactory(dataSourceFactory);
}
public void setDataSourceFactories(List dataSourceFactories) {
if (dataSourceFactories == null || dataSourceFactories.isEmpty()) {
throw new IllegalArgumentException("dataSourceFactories can't be null or empty");
}
dataSourceFactoryGroup = new DataSourceFactoryGroup(dataSourceFactories);
}
public CacheHandler getCacheHandler() {
return cacheHandler;
}
public void setCacheHandler(CacheHandler cacheHandler) {
if (cacheHandler == null) {
throw new NullPointerException("cacheHandler can't be null");
}
this.cacheHandler = cacheHandler;
}
public boolean isLazyInit() {
return isLazyInit;
}
public void setLazyInit(boolean isLazyInit) {
this.isLazyInit = isLazyInit;
}
public void setInterceptorChain(InterceptorChain interceptorChain) {
if (interceptorChain == null) {
throw new NullPointerException("interceptorChain can't be null");
}
this.interceptorChain = interceptorChain;
}
public void setStatMonitor(StatMonitor statMonitor) {
statCollector.initStatMonitor(statMonitor);
}
public void shutDownStatMonitor() {
statCollector.shutDown();
}
private static class MangoInvocationHandler extends AbstractInvocationHandler implements InvocationHandler {
private final Class> daoClass;
private final StatCollector statCollector;
private final OperatorFactory operatorFactory;
private final boolean isUseActualParamName;
private final LoadingCache cache = new DoubleCheckCache(
new CacheLoader() {
public Operator load(Method method) {
if (logger.isInfoEnabled()) {
logger.info("Initializing operator for {}", ToStringHelper.toString(method));
}
CombinedStat combinedStat = statCollector.getCombinedStat(method);
MetaStat metaStat = combinedStat.getMetaStat();
InitStat initStat = combinedStat.getInitStat();
long now = System.nanoTime();
MethodDescriptor md = Methods.getMethodDescriptor(daoClass, method, isUseActualParamName);
Operator operator = operatorFactory.getOperator(md, metaStat);
initStat.recordInit(System.nanoTime() - now);
metaStat.setDaoClass(daoClass);
metaStat.setMethod(method);
metaStat.setSql(md.getSQL());
return operator;
}
});
private MangoInvocationHandler(
Class> daoClass,
DataSourceFactoryGroup dataSourceFactoryGroup,
CacheHandler cacheHandler,
InterceptorChain interceptorChain,
StatCollector statCollector,
Config config) {
this.daoClass = daoClass;
this.statCollector = statCollector;
this.isUseActualParamName = config.isUseActualParamName();
operatorFactory = new OperatorFactory(dataSourceFactoryGroup, cacheHandler, interceptorChain, config);
}
@Override
protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
if (logger.isDebugEnabled()) {
logger.debug("Invoking {}", ToStringHelper.toString(method));
}
Operator operator = getOperator(method);
InvocationStat stat = InvocationStat.create();
try {
Object r = operator.execute(args, stat);
return r;
} finally {
statCollector.getCombinedStat(method).getExecuteStat().accumulate(stat);
}
}
Operator getOperator(Method method) {
return cache.get(method);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy