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 }