+ expose key-generator in the XML namespace
This commit is contained in:
Costin Leau 2011-10-07 19:45:05 +00:00
parent e6d9b6308e
commit a12ebbfded
7 changed files with 84 additions and 10 deletions

View File

@ -16,7 +16,7 @@
package org.springframework.cache.config;
import org.w3c.dom.Element;
import static org.springframework.context.annotation.AnnotationConfigUtils.*;
import org.springframework.aop.config.AopNamespaceUtils;
import org.springframework.beans.factory.config.BeanDefinition;
@ -29,8 +29,7 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cache.annotation.AnnotationCacheOperationSource;
import org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor;
import org.springframework.cache.interceptor.CacheInterceptor;
import static org.springframework.context.annotation.AnnotationConfigUtils.*;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser}
@ -63,10 +62,11 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
private static void registerCacheManagerProperty(Element element, BeanDefinition def) {
private static void parseCacheManagerProperty(Element element, BeanDefinition def) {
def.getPropertyValues().add("cacheManager",
new RuntimeBeanReference(CacheNamespaceHandler.extractCacheManager(element)));
}
@ -87,7 +87,8 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
RootBeanDefinition def = new RootBeanDefinition();
def.setBeanClassName(CACHE_ASPECT_CLASS_NAME);
def.setFactoryMethodName("aspectOf");
registerCacheManagerProperty(element, def);
parseCacheManagerProperty(element, def);
CacheNamespaceHandler.parseKeyGenerator(element, def);
parserContext.registerBeanComponent(new BeanComponentDefinition(def, CACHE_ASPECT_BEAN_NAME));
}
}
@ -114,7 +115,7 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
RootBeanDefinition interceptorDef = new RootBeanDefinition(CacheInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerCacheManagerProperty(element, interceptorDef);
parseCacheManagerProperty(element, interceptorDef);
interceptorDef.getPropertyValues().add("cacheOperationSources", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
@ -138,5 +139,4 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser
}
}
}
}
}

View File

@ -110,6 +110,7 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
builder.addPropertyReference("cacheManager", CacheNamespaceHandler.extractCacheManager(element));
CacheNamespaceHandler.parseKeyGenerator(element, builder.getBeanDefinition());
List<Element> cacheDefs = DomUtils.getChildElementsByTagName(element, DEFS_ELEMENT);
if (cacheDefs.size() >= 1) {

View File

@ -16,7 +16,10 @@
package org.springframework.cache.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
@ -40,9 +43,16 @@ public class CacheNamespaceHandler extends NamespaceHandlerSupport {
: CacheNamespaceHandler.DEFAULT_CACHE_MANAGER_BEAN_NAME);
}
static BeanDefinition parseKeyGenerator(Element element, BeanDefinition def) {
String name = element.getAttribute("key-generator");
if (StringUtils.hasText(name)) {
def.getPropertyValues().add("keyGenerator", new RuntimeBeanReference(name.trim()));
}
return def;
}
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenCacheBeanDefinitionParser());
registerBeanDefinitionParser("advice", new CacheAdviceParser());
}
}

View File

@ -45,6 +45,21 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="key-generator" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.cache.interceptor.KeyGenerator"><![CDATA[
The bean name of the KeyGenerator that is to be used to retrieve the backing caches.
This attribute is not required, and only needs to be specified
explicitly if the default strategy (DefaultKeyGenerator) is not sufficient.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.cache.interceptor.KeyGenerator"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mode" default="proxy">
<xsd:annotation>
<xsd:documentation><![CDATA[
@ -128,6 +143,21 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="key-generator" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.cache.interceptor.KeyGenerator"><![CDATA[
The bean name of the KeyGenerator that is to be used to retrieve the backing caches.
This attribute is not required, and only needs to be specified
explicitly if the default strategy (DefaultKeyGenerator) is not sufficient.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.cache.interceptor.KeyGenerator"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

View File

@ -20,11 +20,13 @@ import static org.junit.Assert.*;
import java.util.UUID;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.CacheInterceptor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@ -284,4 +286,10 @@ public abstract class AbstractAnnotationTests {
public void testClassUncheckedException() throws Exception {
testUncheckedThrowable(ccs);
}
@Test
public void testKeyStrategy() throws Exception {
CacheInterceptor bean = ctx.getBean("cacheAdviceClass", CacheInterceptor.class);
Assert.assertSame(ctx.getBean("keyGenerator"), bean.getKeyGenerator());
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2011 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.
* 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.springframework.cache.config;
import org.springframework.cache.interceptor.DefaultKeyGenerator;
public class SomeKeyGenerator extends DefaultKeyGenerator {
}

View File

@ -22,7 +22,7 @@
</cache:definitions>
</cache:advice>
<cache:advice id="cacheAdviceClass" cache-manager="cacheManager">
<cache:advice id="cacheAdviceClass" cache-manager="cacheManager" key-generator="keyGenerator">
<cache:definitions cache="default">
<cache:cacheable method="key" key="#p0"/>
<cache:cacheable method="nam*" key="#root.methodName + #root.caches[0].name"/>
@ -50,6 +50,8 @@
</set>
</property>
</bean>
<bean id="keyGenerator" class="org.springframework.cache.config.SomeKeyGenerator"/>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>