View Javadoc

1   package org.springframework.cache.interceptor;
2   
3   import org.aopalliance.aop.Advice;
4   import org.springframework.aop.Pointcut;
5   import org.springframework.aop.framework.ProxyFactory;
6   import org.springframework.aop.support.AbstractPointcutAdvisor;
7   import org.springframework.aop.support.AopUtils;
8   import org.springframework.cache.CacheManager;
9   import org.springframework.cache.annotation.AnnotationCacheOperationSource;
10  
11  /**
12   * Methods for creating caching proxies.
13   */
14  public final class CacheProxy {
15      /*
16          WARNING!  This class uses internal spring code and could be subject to breaking
17          changes between Spring releases.
18  
19          This class is needed because Spring does not yet have a way to apply caching advise to
20          existing objects which is required for our remote service proxies.
21  
22          Hopefully, Spring will provide this capability in the future and we can remove this class.
23      */
24  
25  
26      private CacheProxy() {
27          throw new IllegalArgumentException("do not call");
28      }
29  
30      /**
31       * This creates a caching proxy around a existing object if the proxy can be applied.
32       *
33       * @param o the object to proxy.  cannot be null.
34       * @param cacheManager the cacheManager to handle the caching operations.  cannot be null.
35       * @return a proxy.  will not return null.
36       * @throws IllegalArgumentException if the o or cacheManager is null
37       */
38      public static <T> T createCacheProxy(T o, CacheManager cacheManager) {
39          if (o == null) {
40              throw new IllegalArgumentException("o is null");
41          }
42  
43          if (cacheManager == null) {
44              throw new IllegalArgumentException("cacheManager is null");
45          }
46  
47          //this method is following the logic found in AnnotationDrivenCacheBeanDefinitionParser.AopAutoProxyConfigurer
48  
49          final AnnotationCacheOperationSource source = new AnnotationCacheOperationSource();
50  
51          final CacheInterceptor interceptor = new CacheInterceptor();
52          interceptor.setCacheManager(cacheManager);
53          interceptor.setCacheDefinitionSources(source);
54          //important!  must call afterPropertiesSet or does not execute caching logic
55          interceptor.afterPropertiesSet();
56  
57          final ProxyPointcut pointcut = new ProxyPointcut(source);
58          final ProxyPointCutAdvisor advisor = new ProxyPointCutAdvisor(pointcut, interceptor);
59  
60          if (AopUtils.canApply(advisor, o.getClass())) {
61              final ProxyFactory proxyFactory = new ProxyFactory(o);
62              proxyFactory.addAdvisor(advisor);
63              return (T) proxyFactory.getProxy();
64          }
65          return o;
66      }
67  
68      private static class ProxyPointcut extends CacheOperationSourcePointcut {
69          private static final long serialVersionUID = 6050508570006106939L;
70  
71          private final AnnotationCacheOperationSource source;
72  
73          private ProxyPointcut(AnnotationCacheOperationSource source) {
74              this.source = source;
75          }
76  
77          @Override
78          protected CacheOperationSource getCacheOperationSource() {
79              return source;
80          }
81      }
82  
83      private static class ProxyPointCutAdvisor extends AbstractPointcutAdvisor {
84  
85          private static final long serialVersionUID = 6050508570006106939L;
86  
87          private final CacheOperationSourcePointcut pointcut;
88          private final CacheInterceptor interceptor;
89  
90          private ProxyPointCutAdvisor(CacheOperationSourcePointcut pointcut, CacheInterceptor interceptor) {
91              this.pointcut = pointcut;
92              this.interceptor = interceptor;
93          }
94  
95          @Override
96          public Pointcut getPointcut() {
97              return pointcut;
98          }
99  
100         @Override
101         public Advice getAdvice() {
102             return interceptor;
103         }
104     }
105 }