org.jsr107.ri.annotations.spring.config.AnnotationDrivenJCacheBeanDefinitionParser Maven / Gradle / Ivy
/**
* Copyright 2011-2013 Terracotta, Inc.
* Copyright 2011-2013 Oracle America Incorporated
*
* 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.jsr107.ri.annotations.spring.config;
import org.jsr107.ri.annotations.AbstractCacheInterceptor;
import org.jsr107.ri.annotations.DefaultCacheKeyGenerator;
import org.jsr107.ri.annotations.DefaultCacheResolverFactory;
import org.jsr107.ri.annotations.spring.CacheContextSourceImpl;
import org.jsr107.ri.annotations.spring.CachePutInterceptor;
import org.jsr107.ri.annotations.spring.CacheRemoveAllInterceptor;
import org.jsr107.ri.annotations.spring.CacheRemoveEntryInterceptor;
import org.jsr107.ri.annotations.spring.CacheResultInterceptor;
import org.springframework.aop.config.AopNamespaceUtils;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Class that handles the parsing the custom jcache namespace elements in a spring bean definition file
*
* @author Eric Dalquist
*/
public class AnnotationDrivenJCacheBeanDefinitionParser implements BeanDefinitionParser {
private static final String XSD_ATTR_CACHE_MANAGER = "cache-manager";
private static final String JCACHE_CACHE_OPERATION_SOURCE_BEAN_NAME = AnnotationDrivenJCacheBeanDefinitionParser.class
.getPackage().getName() + ".internalJCacheOperationSourceAdvisor";
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element,
* org.springframework.beans.factory.xml.ParserContext)
*/
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
final BeanDefinitionRegistry registry = parserContext.getRegistry();
if (!registry.containsBeanDefinition(JCACHE_CACHE_OPERATION_SOURCE_BEAN_NAME)) {
final Object elementSource = parserContext.extractSource(element);
final RuntimeBeanReference cacheOperationSourceReference = this.setupCacheOperationSource(element,
parserContext,
elementSource);
this.setupPointcutAdvisor(CacheResultInterceptor.class,
element, parserContext, elementSource, cacheOperationSourceReference);
this.setupPointcutAdvisor(CachePutInterceptor.class,
element, parserContext, elementSource, cacheOperationSourceReference);
this.setupPointcutAdvisor(CacheRemoveEntryInterceptor.class,
element, parserContext, elementSource, cacheOperationSourceReference);
this.setupPointcutAdvisor(CacheRemoveAllInterceptor.class,
element, parserContext, elementSource, cacheOperationSourceReference);
return registry.getBeanDefinition(JCACHE_CACHE_OPERATION_SOURCE_BEAN_NAME);
}
return null;
}
/**
* Create a {@link CacheContextSourceImpl} bean that will be used by the advisor and interceptor
*
* @return Reference to the {@link CacheContextSourceImpl}. Should never be null.
*/
protected RuntimeBeanReference setupCacheOperationSource(Element element, ParserContext parserContext,
Object elementSource) {
final RootBeanDefinition cacheAttributeSource = new RootBeanDefinition(CacheContextSourceImpl.class);
cacheAttributeSource.setSource(elementSource);
cacheAttributeSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
final RootBeanDefinition defaultCacheResolverFactory = new RootBeanDefinition(DefaultCacheResolverFactory.class);
cacheAttributeSource.setSource(elementSource);
cacheAttributeSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
final String cacheManagerName = element.getAttribute(XSD_ATTR_CACHE_MANAGER);
if (StringUtils.hasText(cacheManagerName)) {
final RuntimeBeanReference cacheManagerReference = new RuntimeBeanReference(cacheManagerName);
final ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, cacheManagerReference);
cacheAttributeSource.setConstructorArgumentValues(constructorArgumentValues);
}
final RootBeanDefinition defaultCacheKeyGenerator = new RootBeanDefinition(DefaultCacheKeyGenerator.class);
cacheAttributeSource.setSource(elementSource);
cacheAttributeSource.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
final MutablePropertyValues propertyValues = cacheAttributeSource.getPropertyValues();
propertyValues.addPropertyValue("defaultCacheKeyGenerator", defaultCacheKeyGenerator);
propertyValues.addPropertyValue("defaultCacheResolverFactory", defaultCacheResolverFactory);
final BeanDefinitionRegistry registry = parserContext.getRegistry();
registry.registerBeanDefinition(JCACHE_CACHE_OPERATION_SOURCE_BEAN_NAME, cacheAttributeSource);
return new RuntimeBeanReference(JCACHE_CACHE_OPERATION_SOURCE_BEAN_NAME);
}
/**
* Create the {@link RuntimeBeanReference} used to apply the caching interceptor
*
* @return Reference to the {@link RuntimeBeanReference}. Should never be null.
*/
protected RuntimeBeanReference setupPointcut(ParserContext parserContext, Object elementSource,
RuntimeBeanReference cacheOperationSourceRuntimeReference,
RuntimeBeanReference cacheInterceptorSourceRuntimeReference) {
final RootBeanDefinition pointcut = new RootBeanDefinition(CacheStaticMethodMatcherPointcut.class);
pointcut.setSource(elementSource);
pointcut.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
final ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, cacheOperationSourceRuntimeReference);
constructorArgumentValues.addIndexedArgumentValue(1, cacheInterceptorSourceRuntimeReference);
pointcut.setConstructorArgumentValues(constructorArgumentValues);
final String pointcutBeanName = pointcut.getBeanClassName() + "_" + cacheInterceptorSourceRuntimeReference.getBeanName();
final BeanDefinitionRegistry registry = parserContext.getRegistry();
registry.registerBeanDefinition(pointcutBeanName, pointcut);
return new RuntimeBeanReference(pointcutBeanName);
}
/**
* Create {@link org.aopalliance.intercept.MethodInterceptor} that is applies the caching logic to advised methods.
*
* @return Reference to the {@link org.aopalliance.intercept.MethodInterceptor}. Should never be null.
*/
protected RuntimeBeanReference setupInterceptor(Class extends AbstractCacheInterceptor>> interceptorClass,
ParserContext parserContext, Object elementSource,
RuntimeBeanReference cacheOperationSourceRuntimeReference) {
final RootBeanDefinition interceptor = new RootBeanDefinition(interceptorClass);
interceptor.setSource(elementSource);
interceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
final ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, cacheOperationSourceRuntimeReference);
interceptor.setConstructorArgumentValues(constructorArgumentValues);
final XmlReaderContext readerContext = parserContext.getReaderContext();
final String interceptorBeanName = readerContext.registerWithGeneratedName(interceptor);
return new RuntimeBeanReference(interceptorBeanName);
}
/**
* Create {@link org.springframework.aop.PointcutAdvisor} that puts the
* {@link org.springframework.aop.Pointcut} and {@link AbstractCacheInterceptor} together.
*/
protected void setupPointcutAdvisor(Class extends AbstractCacheInterceptor>> interceptorClass,
Element element, ParserContext parserContext,
Object elementSource, RuntimeBeanReference cacheOperationSourceReference) {
final RuntimeBeanReference interceptorReference =
this.setupInterceptor(interceptorClass, parserContext, elementSource, cacheOperationSourceReference);
final RuntimeBeanReference pointcutReference =
this.setupPointcut(parserContext, elementSource, cacheOperationSourceReference, interceptorReference);
final RootBeanDefinition pointcutAdvisor = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
pointcutAdvisor.setSource(elementSource);
pointcutAdvisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
final MutablePropertyValues propertyValues = pointcutAdvisor.getPropertyValues();
propertyValues.addPropertyValue("adviceBeanName", interceptorReference.getBeanName());
propertyValues.addPropertyValue("pointcut", pointcutReference);
if (element.hasAttribute("order")) {
propertyValues.addPropertyValue("order", element.getAttribute("order"));
}
final XmlReaderContext readerContext = parserContext.getReaderContext();
readerContext.registerWithGeneratedName(pointcutAdvisor);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy