001/* 002 * Copyright 2002-2017 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.test.util; 018 019import org.springframework.aop.framework.Advised; 020import org.springframework.aop.support.AopUtils; 021import org.springframework.util.Assert; 022 023/** 024 * {@code AopTestUtils} is a collection of AOP-related utility methods for 025 * use in unit and integration testing scenarios. 026 * 027 * <p>For Spring's core AOP utilities, see 028 * {@link org.springframework.aop.support.AopUtils AopUtils} and 029 * {@link org.springframework.aop.framework.AopProxyUtils AopProxyUtils}. 030 * 031 * @author Sam Brannen 032 * @since 4.2 033 * @see org.springframework.aop.support.AopUtils 034 * @see org.springframework.aop.framework.AopProxyUtils 035 * @see ReflectionTestUtils 036 */ 037public abstract class AopTestUtils { 038 039 /** 040 * Get the <em>target</em> object of the supplied {@code candidate} object. 041 * <p>If the supplied {@code candidate} is a Spring 042 * {@linkplain AopUtils#isAopProxy proxy}, the target of the proxy will 043 * be returned; otherwise, the {@code candidate} will be returned 044 * <em>as is</em>. 045 * @param candidate the instance to check (potentially a Spring AOP proxy; 046 * never {@code null}) 047 * @return the target object or the {@code candidate} (never {@code null}) 048 * @throws IllegalStateException if an error occurs while unwrapping a proxy 049 * @see Advised#getTargetSource() 050 * @see #getUltimateTargetObject 051 */ 052 @SuppressWarnings("unchecked") 053 public static <T> T getTargetObject(Object candidate) { 054 Assert.notNull(candidate, "Candidate must not be null"); 055 try { 056 if (AopUtils.isAopProxy(candidate) && candidate instanceof Advised) { 057 return (T) ((Advised) candidate).getTargetSource().getTarget(); 058 } 059 } 060 catch (Throwable ex) { 061 throw new IllegalStateException("Failed to unwrap proxied object", ex); 062 } 063 return (T) candidate; 064 } 065 066 /** 067 * Get the ultimate <em>target</em> object of the supplied {@code candidate} 068 * object, unwrapping not only a top-level proxy but also any number of 069 * nested proxies. 070 * <p>If the supplied {@code candidate} is a Spring 071 * {@linkplain AopUtils#isAopProxy proxy}, the ultimate target of all 072 * nested proxies will be returned; otherwise, the {@code candidate} 073 * will be returned <em>as is</em>. 074 * @param candidate the instance to check (potentially a Spring AOP proxy; 075 * never {@code null}) 076 * @return the target object or the {@code candidate} (never {@code null}) 077 * @throws IllegalStateException if an error occurs while unwrapping a proxy 078 * @see Advised#getTargetSource() 079 * @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass 080 */ 081 @SuppressWarnings("unchecked") 082 public static <T> T getUltimateTargetObject(Object candidate) { 083 Assert.notNull(candidate, "Candidate must not be null"); 084 try { 085 if (AopUtils.isAopProxy(candidate) && candidate instanceof Advised) { 086 return (T) getUltimateTargetObject(((Advised) candidate).getTargetSource().getTarget()); 087 } 088 } 089 catch (Throwable ex) { 090 throw new IllegalStateException("Failed to unwrap proxied object", ex); 091 } 092 return (T) candidate; 093 } 094 095}