Package org.springmodules.cache.interceptor.proxy

Source Code of org.springmodules.cache.interceptor.proxy.CacheProxyFactoryBean

/*
* Created on Jan 17, 2005
*
* 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.
*
* Copyright @2005 the original author or authors.
*/

package org.springmodules.cache.interceptor.proxy;

import java.util.Map;

import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.aop.framework.ProxyConfig;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ClassUtils;

import org.springmodules.cache.interceptor.caching.CachingListener;
import org.springmodules.cache.interceptor.caching.CachingModelSourceAdvisor;
import org.springmodules.cache.interceptor.caching.NameMatchCachingInterceptor;
import org.springmodules.cache.interceptor.flush.FlushingModelSourceAdvisor;
import org.springmodules.cache.interceptor.flush.NameMatchFlushingInterceptor;
import org.springmodules.cache.key.CacheKeyGenerator;
import org.springmodules.cache.provider.CacheProviderFacade;

/**
* <p>
* Proxy factory bean for simplified declarative caching services.
* </p>
*
* @author Alex Ruiz
*/
public final class CacheProxyFactoryBean extends ProxyConfig implements
    FactoryBean, InitializingBean {

  private static final long serialVersionUID = 3688501099833603120L;

  private NameMatchCachingInterceptor cachingInterceptor;

  private NameMatchFlushingInterceptor flushingInterceptor;

  private boolean hasFlushingModels;

  /**
   * The proxy to create.
   */
  private Object proxy;

  /**
   * Set of interfaces to be implemented by the proxy.
   */
  private Class[] proxyInterfaces;

  private Object target;

  /**
   * Construct a <code>CacheProxyFactoryBean</code>.
   */
  public CacheProxyFactoryBean() {
    super();
    flushingInterceptor = new NameMatchFlushingInterceptor();
    cachingInterceptor = new NameMatchCachingInterceptor();
  }

  /**
   * Creates the proxy for target object. This method is invoked by a
   * BeanFactory after it has set all bean properties supplied.
   *
   * @throws IllegalStateException
   *           if target is <code>null</code>.
   * @throws AopConfigException
   *           if the proxy interfaces or proxyTargetClass are not set and the
   *           target type is <code>org.springframework.aop.TargetSource</code>.
   */
  public void afterPropertiesSet() throws IllegalStateException,
      AopConfigException {
    cachingInterceptor.afterPropertiesSet();
    flushingInterceptor.afterPropertiesSet();

    if (target == null) {
      throw new IllegalStateException("Property 'target' is required");
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.addAdvisor(new CachingModelSourceAdvisor(cachingInterceptor));

    if (hasFlushingModels) {
      proxyFactory.addAdvisor(new FlushingModelSourceAdvisor(
          flushingInterceptor));
    }

    proxyFactory.copyFrom(this);

    TargetSource targetSource = createTargetSource(target);
    proxyFactory.setTargetSource(targetSource);

    if (proxyInterfaces != null) {
      proxyFactory.setInterfaces(proxyInterfaces);
    } else if (!isProxyTargetClass()) {
      if (target instanceof TargetSource) {
        throw new AopConfigException(
            "Either 'proxyInterfaces' or 'proxyTargetClass' is required "
                + "when using a TargetSource as 'target'");
      }

      // rely on AOP infrastructure to tell us what interfaces to proxy
      proxyFactory.setInterfaces(ClassUtils.getAllInterfaces(target));
    }

    proxy = proxyFactory.getProxy();
  }

  /**
   * @return the created AOP proxy.
   */
  public Object getObject() {
    return proxy;
  }

  /**
   * @return the class of the created AOP proxy (if created), the target object
   *         (if set) or <code>null</code>.
   *
   * @see FactoryBean#getObjectType()
   */
  public Class getObjectType() {
    Class objectType = null;

    if (proxy != null) {
      objectType = proxy.getClass();
    } else if (target != null && target instanceof TargetSource) {
      objectType = target.getClass();
    }

    return objectType;
  }

  /**
   * @see FactoryBean#isSingleton()
   */
  public boolean isSingleton() {
    return true;
  }

  /**
   * Sets the generator of cache entry keys.
   *
   * @param cacheKeyGenerator
   *          the new generator of cache entry keys
   */
  public void setCacheKeyGenerator(CacheKeyGenerator cacheKeyGenerator) {
    cachingInterceptor.setCacheKeyGenerator(cacheKeyGenerator);
  }

  /**
   * Sets the cache provider facade for the interceptors
   * <code>{@link #flushingInterceptor}</code> and
   * <code>{@link #cachingInterceptor}</code>.
   *
   * @param cacheProviderFacade
   *          the cache provider facade
   */
  public void setCacheProviderFacade(CacheProviderFacade cacheProviderFacade) {
    flushingInterceptor.setCacheProviderFacade(cacheProviderFacade);
    cachingInterceptor.setCacheProviderFacade(cacheProviderFacade);
  }

  /**
   * Sets the listener to be notified each time an entry is stored in the cache.
   *
   * @param cachingListeners
   *          the new caching listeners
   */
  public void setCachingListeners(CachingListener[] cachingListeners) {
    cachingInterceptor.setCachingListeners(cachingListeners);
  }

  /**
   * Sets the caching models with method names as keys.
   * <p>
   * Note: Method names are always applied to the target class, no matter if
   * defined in an interface or the class itself.
   * <p>
   * Internally, a
   * <code>{@link org.springmodules.cache.interceptor.caching.NameMatchCachingModelSource}</code>
   * will be created from the given properties.
   *
   * @param cachingModels
   *          the new caching models
   *
   * @see org.springmodules.cache.interceptor.caching.NameMatchCachingModelSource
   */
  public void setCachingModels(Map cachingModels) {
    cachingInterceptor.setCachingModels(cachingModels);
  }

  /**
   * Sets the cache-flushing models with method names as keys.
   * <p>
   * Note: Method names are always applied to the target class, no matter if
   * defined in an interface or the class itself.
   * <p>
   * Internally, a
   * <code>{@link org.springmodules.cache.interceptor.flush.NameMatchFlushingModelSource}</code>
   * will be created from the given properties.
   *
   * @param flushingModels
   *          the new flushing models
   *
   * @see org.springmodules.cache.interceptor.flush.NameMatchFlushingModelSource
   */
  public void setFlushingModels(Map flushingModels) {
    hasFlushingModels = flushingModels != null && !flushingModels.isEmpty();

    if (hasFlushingModels) {
      flushingInterceptor.setFlushingModels(flushingModels);
    } else {
      flushingInterceptor.setFlushingModelSource(null);
    }
  }

  /**
   * <p>
   * Specify the set of interfaces being proxied.
   * </p>
   * <p>
   * If left null (the default), the AOP infrastructure works out which
   * interfaces need proxying by analyzing the target, proxying all the
   * interfaces that the target object implements.
   * </p>
   *
   * @param interfaceNames
   *          the interfaces
   * @throws ClassNotFoundException
   *           if any of the classes can't be loaded
   */
  public void setProxyInterfaces(String[] interfaceNames)
      throws ClassNotFoundException {
    proxyInterfaces = toInterfaceArray(interfaceNames);
  }
 
  private Class[] toInterfaceArray(String[] interfaceNames) throws ClassNotFoundException
  {
    Class interfaces[] = new Class[interfaceNames.length];
    for (int i = 0; i < interfaceNames.length; i++) {
      interfaces[i] = ClassUtils.forName(interfaceNames[i].trim());
      // Check whether it is an interface.
      if (!interfaces[i].isInterface()) {
        throw new IllegalArgumentException(
            "Can proxy only interfaces: [" + interfaces[i].getName() + "] is a class");
      }
    }
    return interfaces;
  }

  /**
   * Sets the target object to be proxied.
   *
   * @param newTarget
   *          the new target object
   */
  public void setTarget(Object newTarget) {
    target = newTarget;
  }

  /**
   * Set the target or <code>TargetSource</code>.
   *
   * @param targetObject
   *          target. If this is an implementation of <code>TargetSource</code>
   *          it is used as our <code>TargetSource</code>; otherwise it is
   *          wrapped in a <code>SingletonTargetSource</code>.
   * @return a <code>TargetSource</code> for this object.
   */
  protected TargetSource createTargetSource(Object targetObject) {
    TargetSource targetSource = null;

    if (targetObject instanceof TargetSource) {
      targetSource = (TargetSource) targetObject;
    } else {
      targetSource = new SingletonTargetSource(targetObject);
    }

    return targetSource;
  }

  /**
   * @return the internal caching interceptor
   */
  protected NameMatchCachingInterceptor getCachingInterceptor() {
    return cachingInterceptor;
  }

  /**
   * @return the internal flushing interceptor
   */
  protected NameMatchFlushingInterceptor getFlushingInterceptor() {
    return flushingInterceptor;
  }

  /**
   * @return the created AOP proxy
   */
  protected Object getProxy() {
    return proxy;
  }

  /**
   * @return the interfaces to be implemented by the AOP proxy
   */
  protected Class[] getProxyInterfaces() {
    return proxyInterfaces;
  }

  /**
   * @return <code>true</code> if this proxy factory contains flushing models
   */
  protected boolean isHasFlushingModels() {
    return hasFlushingModels;
  }

}
TOP

Related Classes of org.springmodules.cache.interceptor.proxy.CacheProxyFactoryBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.