diff --git a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/CachingMetadataReaderFactory.java b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/CachingMetadataReaderFactory.java index a44ce7f0673..725b70f9646 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/type/classreading/CachingMetadataReaderFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/type/classreading/CachingMetadataReaderFactory.java @@ -34,9 +34,19 @@ import org.springframework.core.io.ResourceLoader; */ public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory { - private static final int MAX_ENTRIES = 256; + /** Default maximum number of entries for the MetadataReader cache: 256 */ + public static final int DEFAULT_CACHE_LIMIT = 256; - private final Map classReaderCache = createLRUCache(); + + private volatile int cacheLimit = DEFAULT_CACHE_LIMIT; + + private final Map classReaderCache = + new LinkedHashMap(DEFAULT_CACHE_LIMIT, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > getCacheLimit(); + } + }; /** @@ -64,8 +74,27 @@ public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory { } + /** + * Specify the maximum number of entries for the MetadataReader cache. + * Default is 256. + */ + public void setCacheLimit(int cacheLimit) { + this.cacheLimit = cacheLimit; + } + + /** + * Return the maximum number of entries for the MetadataReader cache. + */ + public int getCacheLimit() { + return this.cacheLimit; + } + + @Override public MetadataReader getMetadataReader(Resource resource) throws IOException { + if (getCacheLimit() <= 0) { + return super.getMetadataReader(resource); + } synchronized (this.classReaderCache) { MetadataReader metadataReader = this.classReaderCache.get(resource); if (metadataReader == null) { @@ -76,15 +105,4 @@ public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory { } } - - @SuppressWarnings("serial") - private static Map createLRUCache() { - return new LinkedHashMap(MAX_ENTRIES, 0.75f, true) { - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > MAX_ENTRIES; - } - }; - } - } diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java index feca9e1e53e..65f50b1b988 100644 --- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,9 @@ package org.springframework.jdbc.core.namedparam; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; - import javax.sql.DataSource; import org.springframework.dao.DataAccessException; @@ -60,11 +59,23 @@ import org.springframework.util.Assert; */ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations { + /** Default maximum number of entries for this template's SQL cache: 256 */ + public static final int DEFAULT_CACHE_LIMIT = 256; + + /** The JdbcTemplate we are wrapping */ private final JdbcOperations classicJdbcTemplate; - /** Map of original SQL String to ParsedSql representation */ - private final Map parsedSqlCache = new HashMap(); + private volatile int cacheLimit = DEFAULT_CACHE_LIMIT; + + /** Cache of original SQL String to ParsedSql representation */ + private final Map parsedSqlCache = + new LinkedHashMap(DEFAULT_CACHE_LIMIT, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > getCacheLimit(); + } + }; /** @@ -73,7 +84,7 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations * @param dataSource the JDBC DataSource to access */ public NamedParameterJdbcTemplate(DataSource dataSource) { - Assert.notNull(dataSource, "The [dataSource] argument cannot be null."); + Assert.notNull(dataSource, "DataSource must not be null"); this.classicJdbcTemplate = new JdbcTemplate(dataSource); } @@ -96,6 +107,21 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return this.classicJdbcTemplate; } + /** + * Specify the maximum number of entries for this template's SQL cache. + * Default is 256. + */ + public void setCacheLimit(int cacheLimit) { + this.cacheLimit = cacheLimit; + } + + /** + * Return the maximum number of entries for this template's SQL cache. + */ + public int getCacheLimit() { + return this.cacheLimit; + } + public T execute(String sql, SqlParameterSource paramSource, PreparedStatementCallback action) throws DataAccessException { @@ -294,10 +320,15 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations /** * Obtain a parsed representation of the given SQL statement. + *

The default implementation uses an LRU cache with an upper limit + * of 256 entries. * @param sql the original SQL * @return a representation of the parsed SQL statement */ protected ParsedSql getParsedSql(String sql) { + if (getCacheLimit() <= 0) { + return NamedParameterUtils.parseSqlStatement(sql); + } synchronized (this.parsedSqlCache) { ParsedSql parsedSql = this.parsedSqlCache.get(sql); if (parsedSql == null) {