View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.springframework.cache.interceptor;
17  
18  import org.aopalliance.aop.Advice;
19  import org.springframework.aop.Pointcut;
20  import org.springframework.aop.framework.ProxyFactory;
21  import org.springframework.aop.support.AbstractPointcutAdvisor;
22  import org.springframework.aop.support.AopUtils;
23  import org.springframework.cache.CacheManager;
24  import org.springframework.cache.annotation.AnnotationCacheOperationSource;
25  
26  /**
27   * Methods for creating caching proxies.
28   */
29  public final class CacheProxy {
30      /*
31          WARNING!  This class uses internal spring code and could be subject to breaking
32          changes between Spring releases.
33  
34          This class is needed because Spring does not yet have a way to apply caching advise to
35          existing objects which is required for our remote service proxies.
36  
37          Hopefully, Spring will provide this capability in the future and we can remove this class.
38      */
39  
40  
41      private CacheProxy() {
42          throw new IllegalArgumentException("do not call");
43      }
44  
45      /**
46       * This creates a caching proxy around a existing object if the proxy can be applied.
47       *
48       * @param o the object to proxy.  cannot be null.
49       * @param cacheManager the cacheManager to handle the caching operations.  cannot be null.
50       * @return a proxy.  will not return null.
51       * @throws IllegalArgumentException if the o or cacheManager is null
52       */
53      public static <T> T createCacheProxy(T o, CacheManager cacheManager) {
54          if (o == null) {
55              throw new IllegalArgumentException("o is null");
56          }
57  
58          if (cacheManager == null) {
59              throw new IllegalArgumentException("cacheManager is null");
60          }
61  
62          //this method is following the logic found in AnnotationDrivenCacheBeanDefinitionParser.AopAutoProxyConfigurer
63  
64          final AnnotationCacheOperationSource source = new AnnotationCacheOperationSource();
65  
66          final CacheInterceptor interceptor = new CacheInterceptor();
67          interceptor.setCacheManager(cacheManager);
68          interceptor.setCacheOperationSources(source);
69          //important!  must call afterPropertiesSet or does not execute caching logic
70          interceptor.afterPropertiesSet();
71  
72          final ProxyPointcut pointcut = new ProxyPointcut(source);
73          final ProxyPointCutAdvisor advisor = new ProxyPointCutAdvisor(pointcut, interceptor);
74  
75          if (AopUtils.canApply(advisor, o.getClass())) {
76              final ProxyFactory proxyFactory = new ProxyFactory(o);
77              proxyFactory.addAdvisor(advisor);
78              return (T) proxyFactory.getProxy();
79          }
80          return o;
81      }
82  
83      private static class ProxyPointcut extends CacheOperationSourcePointcut {
84          private static final long serialVersionUID = 6050508570006106939L;
85  
86          private final AnnotationCacheOperationSource source;
87  
88          private ProxyPointcut(AnnotationCacheOperationSource source) {
89              this.source = source;
90          }
91  
92          @Override
93          protected CacheOperationSource getCacheOperationSource() {
94              return source;
95          }
96      }
97  
98      private static class ProxyPointCutAdvisor extends AbstractPointcutAdvisor {
99  
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 }