基于昨天的demo,我们这里再进行进一步的一些探索: 首先我们再编写两个测试类,以完成动态数据源抽取的部分功能:
public void init() {
try {
DruidDataSource druidDataSource = DataSourceToolsUtils.getDataSource("dynamic", "com.mysql.jdbc.Driver",
"jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC", "root", "root");
} catch (SQLException e) {
e.printStackTrace();
}
}
public Map<String,Object> getDataSourceStat(String name) {
return DataSourceToolsUtils.getDataSourceStat(name);
}
复制代码
上面的方法初始化连接池,下面的方法用于根据刚刚初始化的连接池名称拿到连接池具体信息, 执行的结果如下:
然后我们就可以根据取到的连接池去做业务了。 由我们刚刚的代码可以得知;DruidDataSourceStatManager
就是druid用于管理已经初始化连接池的方法.
public class DruidDataSourceStatManager implements DruidDataSourceStatManagerMBean {
private static final Lock staticLock = new ReentrantLock();
public static final String SYS_PROP_INSTANCES = "druid.dataSources";
public static final String SYS_PROP_REGISTER_SYS_PROPERTY = "druid.registerToSysProperty";
private static final Log LOG = LogFactory.getLog(DruidDataSourceStatManager.class);
private static final DruidDataSourceStatManager instance = new DruidDataSourceStatManager();
private final AtomicLong resetCount = new AtomicLong();
private static volatile Map dataSources;
private static final String MBEAN_NAME = "com.alibaba.druid:type=DruidDataSourceStat";
private static CompositeType COMPOSITE_TYPE = null;
复制代码
在DruidDataSourceStatManager里面我们可以看到 private static volatile Map dataSources; 这个map就是 statManager用来在缓存中保存dataSources的信息的 map, 我们在 getInstance方法中打上断点来看执行的情况: 首先初始化一个名字叫dyamic1的连接池,这里可以看到tmp获得的结果是空的,判断逻辑上可重入锁,然后去系统配置中查看有没有初始化已经完成的连接池,如果没有就把tmp和datasources都赋值。
然后我们再创建一个一个名字叫dyamic3的连接池
然后我们可以看到这里调用了addDataSources方法添加了一个实例。
这些添加实例,初始化整个连接池 信息map类,都是线程安全的。
这里的代码有很多可以借鉴的地方。
public static synchronized ObjectName addDataSource(Object dataSource, String name) {
Map<Object, ObjectName> instances = getInstances();
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
synchronized(instances) {
if (instances.size() == 0) {
try {
ObjectName objectName = new ObjectName("com.alibaba.druid:type=DruidDataSourceStat");
if (!mbeanServer.isRegistered(objectName)) {
mbeanServer.registerMBean(instance, objectName);
}
} catch (JMException var9) {
LOG.error("register mbean error", var9);
}
DruidStatService.registerMBean();
}
}
ObjectName objectName = null;
if (name != null) {
try {
objectName = new ObjectName("com.alibaba.druid:type=DruidDataSource,id=" + name);
mbeanServer.registerMBean(dataSource, objectName);
} catch (Throwable var8) {
LOG.error("register mbean error", var8);
objectName = null;
}
}
if (objectName == null) {
try {
int id = System.identityHashCode(dataSource);
objectName = new ObjectName("com.alibaba.druid:type=DruidDataSource,id=" + id);
mbeanServer.registerMBean(dataSource, objectName);
} catch (Throwable var7) {
LOG.error("register mbean error", var7);
objectName = null;
}
}
instances.put(dataSource, objectName);
return objectName;
}
复制代码
这里看到之前不理解的方法就可以理解了,通过初始化时候传入的名称在stat管理map中添加实例,如果没有传入名称生成一个id来标示这个连接池资源,同时druid可以提供多个相互隔离的连接池资源,这样大大加强了druid的能力。