diff --git a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java index 39337d67f5..7a0070c01d 100644 --- a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java +++ b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java @@ -1,5 +1,8 @@ package com.alibaba.druid.stat; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -10,66 +13,144 @@ import com.alibaba.druid.util.ReflectionUtils; public class DruidDataSourceStatJNDIStatStrategy implements DruidDataSourceStatStrategy { - private final static Log LOG = LogFactory.getLog(DruidDataSourceStatJNDIStatStrategy.class); + private final static Log LOG = LogFactory.getLog(DruidDataSourceStatJNDIStatStrategy.class); - private Object getStatDefaultStrategy() { + private final static List strategyList = new ArrayList(); + + private final static HashMap> classMethodHM = new HashMap>(); + + private final static String[] methodNameArr = new String[] { "getSqlStatData", + "getSqlStatDataList", "getActiveConnectionStackTraceByDataSourceId", "returnJSONBasicStat", + "getDataSourceStatList", "getDataSourceStatData", "getPoolingConnectionInfoByDataSourceId", "resetAll", + "getDruidDataSourceById", "getSqlStatById" }; + + public DruidDataSourceStatJNDIStatStrategy(){ + init(); + } + + private void init() { try { - Class clazz = ReflectionUtils.getClassFromWebContainerOrCurrentClassLoader("com.alibaba.druid.stat.DruidDataSourceStatDefaultStrategy"); - return clazz.newInstance(); + // cache the class + String className = "com.alibaba.druid.stat.DruidDataSourceStatDefaultStrategy"; + Class clazzFromWebContainer = ReflectionUtils.getClassFromWebContainer(className); + Class clazzFromCurClassLoader = ReflectionUtils.getClassFromCurrentClassLoader(className); + if (clazzFromWebContainer != null) strategyList.add(clazzFromWebContainer.newInstance()); + if (clazzFromCurClassLoader != null) strategyList.add(clazzFromCurClassLoader.newInstance()); + + // cache the method + Object obj = null; + for (int i = 0; i < strategyList.size(); i++) { + obj = strategyList.get(i); + HashMap methodHM = null; + String methodName = null; + for (int j = 0; j < methodNameArr.length; j++) { + methodHM = new HashMap(); + methodName = methodNameArr[j]; + methodHM.put(methodName, ReflectionUtils.getObjectMethod(obj, methodName)); + } + classMethodHM.put(obj, methodHM); + } } catch (Exception e) { LOG.error(e.getMessage(), e); - return null; } } + @SuppressWarnings("unchecked") + private Object invoke(String methodName, Integer methodParam) { + Object result = null; + try { + HashMap hm = null; + Object invokeRes = null; + Object obj = null; + for (int i = 0; i < strategyList.size(); i++) { + obj = strategyList.get(i); + hm = classMethodHM.get(obj); + if (hm.containsKey(methodName)) { + if (methodParam == null) { + invokeRes = hm.get(methodName).invoke(obj); + } else { + invokeRes = hm.get(methodName).invoke(obj, methodParam); + } + if (invokeRes instanceof Map) { + result = invokeMapResHandler(null, (Map) invokeRes); + } else if (invokeRes instanceof List) { + result = invokeListResHandler(null, (List>) invokeRes); + } + } + } + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + return result; + } + + private Map invokeMapResHandler(Map finalRs, Map invokeRes) { + Map res = null; + if (finalRs == null) { + res = finalRs; + } else { + finalRs.putAll(invokeRes); + res = finalRs; + } + return res; + } + + private List invokeListResHandler(List> finalRs, List> invokeRes) { + List> res = null; + if (finalRs == null) { + res = finalRs; + } else { + finalRs.addAll(invokeRes); + res = finalRs; + } + return res; + } + @SuppressWarnings("unchecked") public Map getSqlStatData(Integer id) { - return (Map) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "getSqlStatData", id); - } - - @SuppressWarnings("unchecked") - public List> getSqlStatDataList() { - return (List>) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "getSqlStatDataList"); - } - - @SuppressWarnings("unchecked") - public List getActiveConnectionStackTraceByDataSourceId(Integer id) { - return (List) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), - "getActiveConnectionStackTraceByDataSourceId", id); - } - - @SuppressWarnings("unchecked") - public Map returnJSONBasicStat() { - return (Map) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "returnJSONBasicStat"); - } - - @SuppressWarnings("unchecked") - public List getDataSourceStatList() { - return (List) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "getDataSourceStatList"); + return (Map) invoke("getSqlStatData", id); } @SuppressWarnings("unchecked") public Map getDataSourceStatData(Integer id) { - return (Map) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "getDataSourceStatData", id); + return (Map) invoke("getDataSourceStatData", id); + } + + @SuppressWarnings("unchecked") + public Map returnJSONBasicStat() { + return (Map) invoke("returnJSONBasicStat", null); + } + + @SuppressWarnings("unchecked") + public List> getSqlStatDataList() { + return (List>) invoke("getSqlStatDataList", null); + } + + @SuppressWarnings("unchecked") + public List getActiveConnectionStackTraceByDataSourceId(Integer id) { + return (List) invoke("getActiveConnectionStackTraceByDataSourceId", id); + } + + @SuppressWarnings("unchecked") + public List getDataSourceStatList() { + return (List) invoke("getDataSourceStatList", null); } @SuppressWarnings("unchecked") public List> getPoolingConnectionInfoByDataSourceId(Integer id) { - return (List>) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), - "getPoolingConnectionInfoByDataSourceId", - id); + return (List>) invoke("getPoolingConnectionInfoByDataSourceId", id); } public void resetAll() { - ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "resetAll"); + invoke("resetAll", null); } public DruidDataSource getDruidDataSourceById(Integer id) { - return (DruidDataSource) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "getDruidDataSourceById"); + return (DruidDataSource) invoke("getDruidDataSourceById", id); } public JdbcSqlStat getSqlStatById(Integer id) { - return (JdbcSqlStat) ReflectionUtils.callObjectMethod(getStatDefaultStrategy(), "getSqlStatById", id); + return (JdbcSqlStat) invoke("getSqlStatById", id); } } diff --git a/src/main/java/com/alibaba/druid/util/ReflectionUtils.java b/src/main/java/com/alibaba/druid/util/ReflectionUtils.java index 223a861cd6..5ead770179 100644 --- a/src/main/java/com/alibaba/druid/util/ReflectionUtils.java +++ b/src/main/java/com/alibaba/druid/util/ReflectionUtils.java @@ -14,19 +14,30 @@ public class ReflectionUtils { private final static Log LOG = LogFactory.getLog(ReflectionUtils.class); - public static Class getClassFromWebContainerOrCurrentClassLoader(String className) { + public static Class getClassFromWebContainer(String className) { Class result = null; try { result = HttpServletRequest.class.getClassLoader().loadClass(className); } catch (ClassNotFoundException e) { if (LOG.isDebugEnabled()) LOG.debug("can'r find class in web container classLoader ", e); } + return result; + } + + public static Class getClassFromCurrentClassLoader(String className) { + Class result = null; + try { + result = Thread.currentThread().getContextClassLoader().loadClass(className); + } catch (ClassNotFoundException e) { + LOG.error("can'r find class in current thread context classLoader ", e); + } + return result; + } + + public static Class getClassFromWebContainerOrCurrentClassLoader(String className) { + Class result = getClassFromWebContainer(className); if (result == null) { - try { - result = Thread.currentThread().getContextClassLoader().loadClass(className); - } catch (ClassNotFoundException e) { - LOG.error("can'r find class in current thread context classLoader ", e); - } + result = getClassFromCurrentClassLoader(className); } return result; } @@ -51,7 +62,25 @@ public class ReflectionUtils { return null; } } - + + public static Method getObjectMethod(Object obj, String methodName) { + try { + return obj.getClass().getMethod(methodName); + } catch (Exception e) { + LOG.warn("getObjectMethod fail:class=" + obj.getClass().getName() + " method=" + methodName, e); + return null; + } + } + + public static Method getObjectMethod(Object obj, String methodName, Integer id) { + try { + return obj.getClass().getMethod(methodName, Integer.class); + } catch (Exception e) { + LOG.warn("getObjectMethod fail:class=" + obj.getClass().getName() + " method=" + methodName, e); + return null; + } + } + public static Object callObjectMethod(Object obj, String methodName, Integer id) { try { Method m = obj.getClass().getMethod(methodName, Integer.class);