001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache 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 * https://www.apache.org/licenses/LICENSE-2.0 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 017package org.springframework.aop.framework; 018 019import org.springframework.core.NamedThreadLocal; 020 021/** 022 * Class containing static methods used to obtain information about the current AOP invocation. 023 * 024 * <p>The {@code currentProxy()} method is usable if the AOP framework is configured to 025 * expose the current proxy (not the default). It returns the AOP proxy in use. Target objects 026 * or advice can use this to make advised calls, in the same way as {@code getEJBObject()} 027 * can be used in EJBs. They can also use it to find advice configuration. 028 * 029 * <p>Spring's AOP framework does not expose proxies by default, as there is a performance cost 030 * in doing so. 031 * 032 * <p>The functionality in this class might be used by a target object that needed access 033 * to resources on the invocation. However, this approach should not be used when there is 034 * a reasonable alternative, as it makes application code dependent on usage under AOP and 035 * the Spring AOP framework in particular. 036 * 037 * @author Rod Johnson 038 * @author Juergen Hoeller 039 * @since 13.03.2003 040 */ 041public abstract class AopContext { 042 043 /** 044 * ThreadLocal holder for AOP proxy associated with this thread. 045 * Will contain {@code null} unless the "exposeProxy" property on 046 * the controlling proxy configuration has been set to "true". 047 * @see ProxyConfig#setExposeProxy 048 */ 049 private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<Object>("Current AOP proxy"); 050 051 052 /** 053 * Try to return the current AOP proxy. This method is usable only if the 054 * calling method has been invoked via AOP, and the AOP framework has been set 055 * to expose proxies. Otherwise, this method will throw an IllegalStateException. 056 * @return Object the current AOP proxy (never returns {@code null}) 057 * @throws IllegalStateException if the proxy cannot be found, because the 058 * method was invoked outside an AOP invocation context, or because the 059 * AOP framework has not been configured to expose the proxy 060 */ 061 public static Object currentProxy() throws IllegalStateException { 062 Object proxy = currentProxy.get(); 063 if (proxy == null) { 064 throw new IllegalStateException( 065 "Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available."); 066 } 067 return proxy; 068 } 069 070 /** 071 * Make the given proxy available via the {@code currentProxy()} method. 072 * <p>Note that the caller should be careful to keep the old value as appropriate. 073 * @param proxy the proxy to expose (or {@code null} to reset it) 074 * @return the old proxy, which may be {@code null} if none was bound 075 * @see #currentProxy() 076 */ 077 static Object setCurrentProxy(Object proxy) { 078 Object old = currentProxy.get(); 079 if (proxy != null) { 080 currentProxy.set(proxy); 081 } 082 else { 083 currentProxy.remove(); 084 } 085 return old; 086 } 087 088}