001 /**
002 * Copyright 2005-2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.springframework.cache.interceptor;
017
018 import org.aopalliance.aop.Advice;
019 import org.springframework.aop.Pointcut;
020 import org.springframework.aop.framework.ProxyFactory;
021 import org.springframework.aop.support.AbstractPointcutAdvisor;
022 import org.springframework.aop.support.AopUtils;
023 import org.springframework.cache.CacheManager;
024 import org.springframework.cache.annotation.AnnotationCacheOperationSource;
025
026 /**
027 * Methods for creating caching proxies.
028 */
029 public final class CacheProxy {
030 /*
031 WARNING! This class uses internal spring code and could be subject to breaking
032 changes between Spring releases.
033
034 This class is needed because Spring does not yet have a way to apply caching advise to
035 existing objects which is required for our remote service proxies.
036
037 Hopefully, Spring will provide this capability in the future and we can remove this class.
038 */
039
040
041 private CacheProxy() {
042 throw new IllegalArgumentException("do not call");
043 }
044
045 /**
046 * This creates a caching proxy around a existing object if the proxy can be applied.
047 *
048 * @param o the object to proxy. cannot be null.
049 * @param cacheManager the cacheManager to handle the caching operations. cannot be null.
050 * @return a proxy. will not return null.
051 * @throws IllegalArgumentException if the o or cacheManager is null
052 */
053 public static <T> T createCacheProxy(T o, CacheManager cacheManager) {
054 if (o == null) {
055 throw new IllegalArgumentException("o is null");
056 }
057
058 if (cacheManager == null) {
059 throw new IllegalArgumentException("cacheManager is null");
060 }
061
062 //this method is following the logic found in AnnotationDrivenCacheBeanDefinitionParser.AopAutoProxyConfigurer
063
064 final AnnotationCacheOperationSource source = new AnnotationCacheOperationSource();
065
066 final CacheInterceptor interceptor = new CacheInterceptor();
067 interceptor.setCacheManager(cacheManager);
068 interceptor.setCacheOperationSources(source);
069 //important! must call afterPropertiesSet or does not execute caching logic
070 interceptor.afterPropertiesSet();
071
072 final ProxyPointcut pointcut = new ProxyPointcut(source);
073 final ProxyPointCutAdvisor advisor = new ProxyPointCutAdvisor(pointcut, interceptor);
074
075 if (AopUtils.canApply(advisor, o.getClass())) {
076 final ProxyFactory proxyFactory = new ProxyFactory(o);
077 proxyFactory.addAdvisor(advisor);
078 return (T) proxyFactory.getProxy();
079 }
080 return o;
081 }
082
083 private static class ProxyPointcut extends CacheOperationSourcePointcut {
084 private static final long serialVersionUID = 6050508570006106939L;
085
086 private final AnnotationCacheOperationSource source;
087
088 private ProxyPointcut(AnnotationCacheOperationSource source) {
089 this.source = source;
090 }
091
092 @Override
093 protected CacheOperationSource getCacheOperationSource() {
094 return source;
095 }
096 }
097
098 private static class ProxyPointCutAdvisor extends AbstractPointcutAdvisor {
099
100 private static final long serialVersionUID = 6050508570006106939L;
101
102 private final CacheOperationSourcePointcut pointcut;
103 private final CacheInterceptor interceptor;
104
105 private ProxyPointCutAdvisor(CacheOperationSourcePointcut pointcut, CacheInterceptor interceptor) {
106 this.pointcut = pointcut;
107 this.interceptor = interceptor;
108 }
109
110 @Override
111 public Pointcut getPointcut() {
112 return pointcut;
113 }
114
115 @Override
116 public Advice getAdvice() {
117 return interceptor;
118 }
119 }
120 }