前面介绍完了连接池的大体流程,今天来梳理Druid中内置Filter的加载。整体流程图如下:
在Demo0中添加如下代码:
dataSource.setFilters("config");
这里代码实际上是调用了DruidAbstractDataSource的set方法。代码如下:
public void setFilters(String filters) throws SQLException {
if (filters != null && filters.startsWith("!")) {
filters = filters.substring(1);
this.clearFilters();
}
this.addFilters(filters);
}
public void addFilters(String filters) throws SQLException {
if (filters == null || filters.length() == 0) {
return;
}
String[] filterArray = filters.split("\\,");
for (String item : filterArray) {
FilterManager.loadFilter(this.filters, item.trim());
}
}
这里面的关键方法是:FilterManager.loadFilter。这行代码就加载了FilterManager类。这里类的静态代码块就会被执行。代码如下:
static {
try {
Properties filterProperties = loadFilterConfig();
for (Map.Entry<Object, Object> entry : filterProperties.entrySet()) {
String key = (String) entry.getKey();
if (key.startsWith("druid.filters.")) {
String name = key.substring("druid.filters.".length());
aliasMap.put(name, (String) entry.getValue());
}
}
} catch (Throwable e) {
LOG.error("load filter config error", e);
}
}
这里调用了loadFilterConfig加载内置Filter的配置信息。代码如下:
private static void loadFilterConfig(Properties filterProperties, ClassLoader classLoader) throws IOException {
if (classLoader == null) {
return;
}
for (Enumeration<URL> e = classLoader.getResources("META-INF/druid-filter.properties"); e.hasMoreElements();) {
URL url = e.nextElement();
Properties property = new Properties();
InputStream is = null;
try {
is = url.openStream();
property.load(is);
} finally {
JdbcUtils.close(is);
}
filterProperties.putAll(property);
}
}
内置的Filter的配置信息是在META-INF/druid-filter.properties 中。
加载完配置信息后调用FilterManager.loadFilter方法把Filter对象放入Filter集合中。代码如下:
public static void loadFilter(List<Filter> filters, String filterName) throws SQLException {
if (filterName.length() == 0) {
return;
}
String filterClassNames = getFilter(filterName);
if (filterClassNames != null) {
for (String filterClassName : filterClassNames.split(",")) {
if (existsFilter(filters, filterClassName)) {
continue;
}
Class<?> filterClass = Utils.loadClass(filterClassName);
if (filterClass == null) {
LOG.error("load filter error, filter not found : " + filterClassName);
continue;
}
Filter filter;
try {
filter = (Filter) filterClass.newInstance();
} catch (ClassCastException e) {
LOG.error("load filter error.", e);
continue;
} catch (InstantiationException e) {
throw new SQLException("load managed jdbc driver event listener error. " + filterName, e);
} catch (IllegalAccessException e) {
throw new SQLException("load managed jdbc driver event listener error. " + filterName, e);
} catch (RuntimeException e) {
throw new SQLException("load managed jdbc driver event listener error. " + filterName, e);
}
filters.add(filter);
}
return;
}
if (existsFilter(filters, filterName)) {
return;
}
Class<?> filterClass = Utils.loadClass(filterName);
if (filterClass == null) {
LOG.error("load filter error, filter not found : " + filterName);
return;
}
try {
Filter filter = (Filter) filterClass.newInstance();
filters.add(filter);
} catch (Exception e) {
throw new SQLException("load managed jdbc driver event listener error. " + filterName, e);
}
}
至此,内置的Filter就加载完毕。
总结
- 通过在DataSource对象设置setFilter字符串来加载内置Filter.
- 内置配置信息是在META-INF/druid-filter.properties 文件中。是通过加载FilterManager类时执行静态代码块加载的。静态代码块在数据库驱动中也有使用。静态代码块保证了代码只执行一次。
- 实例化对象还是通过Class来创建的。