AbstractAutoProxyCreator.java 22.3 KB
Newer Older
1
/*
2
 * Copyright 2002-2019 the original author or authors.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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.
 */

package org.springframework.aop.framework.autoproxy;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
23
import java.util.Collections;
24 25
import java.util.List;
import java.util.Map;
26
import java.util.Set;
27
import java.util.concurrent.ConcurrentHashMap;
28 29 30 31 32 33

import org.aopalliance.aop.Advice;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aop.Advisor;
34
import org.springframework.aop.Pointcut;
35 36 37
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.aop.framework.ProxyFactory;
38
import org.springframework.aop.framework.ProxyProcessorSupport;
39 40 41 42 43 44 45
import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry;
import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
46
import org.springframework.beans.factory.FactoryBean;
47 48 49
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
50
import org.springframework.util.StringUtils;
51 52 53 54 55 56 57

/**
 * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
 * that wraps each eligible bean with an AOP proxy, delegating to specified interceptors
 * before invoking the bean itself.
 *
 * <p>This class distinguishes between "common" interceptors: shared for all proxies it
J
Juergen Hoeller 已提交
58 59 60 61 62 63
 * creates, and "specific" interceptors: unique per bean instance. There need not be any
 * common interceptors. If there are, they are set using the interceptorNames property.
 * As with {@link org.springframework.aop.framework.ProxyFactoryBean}, interceptors names
 * in the current factory are used rather than bean references to allow correct handling
 * of prototype advisors and interceptors: for example, to support stateful mixins.
 * Any advice type is supported for {@link #setInterceptorNames "interceptorNames"} entries.
64 65 66 67 68 69
 *
 * <p>Such auto-proxying is particularly useful if there's a large number of beans that
 * need to be wrapped with similar proxies, i.e. delegating to the same interceptors.
 * Instead of x repetitive proxy definitions for x target beans, you can register
 * one single such post processor with the bean factory to achieve the same effect.
 *
J
Juergen Hoeller 已提交
70 71 72 73
 * <p>Subclasses can apply any strategy to decide if a bean is to be proxied, e.g. by type,
 * by name, by definition details, etc. They can also return additional interceptors that
 * should just be applied to the specific bean instance. A simple concrete implementation is
 * {@link BeanNameAutoProxyCreator}, identifying the beans to be proxied via given names.
74 75
 *
 * <p>Any number of {@link TargetSourceCreator} implementations can be used to create
J
Juergen Hoeller 已提交
76
 * a custom target source: for example, to pool prototype objects. Auto-proxying will
77 78 79 80 81 82 83 84 85 86 87 88 89 90
 * occur even if there is no advice, as long as a TargetSourceCreator specifies a custom
 * {@link org.springframework.aop.TargetSource}. If there are no TargetSourceCreators set,
 * or if none matches, a {@link org.springframework.aop.target.SingletonTargetSource}
 * will be used by default to wrap the target bean instance.
 *
 * @author Juergen Hoeller
 * @author Rod Johnson
 * @author Rob Harrop
 * @since 13.10.2003
 * @see #setInterceptorNames
 * @see #getAdvicesAndAdvisorsForBean
 * @see BeanNameAutoProxyCreator
 * @see DefaultAdvisorAutoProxyCreator
 */
P
Phillip Webb 已提交
91
@SuppressWarnings("serial")
92 93
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

	/**
	 * Convenience constant for subclasses: Return value for "do not proxy".
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	protected static final Object[] DO_NOT_PROXY = null;

	/**
	 * Convenience constant for subclasses: Return value for
	 * "proxy without additional interceptors, just the common ones".
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];


	/** Logger available to subclasses */
	protected final Log logger = LogFactory.getLog(getClass());

	/** Default is global AdvisorAdapterRegistry */
	private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

	/**
	 * Indicates whether or not the proxy should be frozen. Overridden from super
	 * to prevent the configuration from becoming frozen too early.
	 */
	private boolean freezeProxy = false;

	/** Default is no common interceptors */
	private String[] interceptorNames = new String[0];

	private boolean applyCommonInterceptorsFirst = true;

	private TargetSourceCreator[] customTargetSourceCreators;

	private BeanFactory beanFactory;

130 131
	private final Set<String> targetSourcedBeans =
			Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
132

133
	private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<Object, Object>(16);
134

135
	private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<Object, Class<?>>(16);
136

137 138
	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(256);

139 140 141 142 143 144 145

	/**
	 * Set whether or not the proxy should be frozen, preventing advice
	 * from being added to it once it is created.
	 * <p>Overridden from the super class to prevent the proxy configuration
	 * from being frozen before the proxy is created.
	 */
146
	@Override
147 148 149 150
	public void setFrozen(boolean frozen) {
		this.freezeProxy = frozen;
	}

151
	@Override
152 153 154 155 156
	public boolean isFrozen() {
		return this.freezeProxy;
	}

	/**
J
Juergen Hoeller 已提交
157 158
	 * Specify the {@link AdvisorAdapterRegistry} to use.
	 * <p>Default is the global {@link AdvisorAdapterRegistry}.
159 160 161 162 163 164 165
	 * @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry
	 */
	public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
		this.advisorAdapterRegistry = advisorAdapterRegistry;
	}

	/**
J
Juergen Hoeller 已提交
166 167
	 * Set custom {@code TargetSourceCreators} to be applied in this order.
	 * If the list is empty, or they all return null, a {@link SingletonTargetSource}
168 169
	 * will be created for each bean.
	 * <p>Note that TargetSourceCreators will kick in even for target beans
J
Juergen Hoeller 已提交
170 171
	 * where no advices or advisors have been found. If a {@code TargetSourceCreator}
	 * returns a {@link TargetSource} for a specific bean, that bean will be proxied
172
	 * in any case.
J
Juergen Hoeller 已提交
173 174 175 176 177
	 * <p>{@code TargetSourceCreators} can only be invoked if this post processor is used
	 * in a {@link BeanFactory} and its {@link BeanFactoryAware} callback is triggered.
	 * @param targetSourceCreators the list of {@code TargetSourceCreators}.
	 * Ordering is significant: The {@code TargetSource} returned from the first matching
	 * {@code TargetSourceCreator} (that is, the first that returns non-null) will be used.
178
	 */
179
	public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
180 181 182 183 184 185 186 187 188 189
		this.customTargetSourceCreators = targetSourceCreators;
	}

	/**
	 * Set the common interceptors. These must be bean names in the current factory.
	 * They can be of any advice or advisor type Spring supports.
	 * <p>If this property isn't set, there will be zero common interceptors.
	 * This is perfectly valid, if "specific" interceptors such as matching
	 * Advisors are all we want.
	 */
190
	public void setInterceptorNames(String... interceptorNames) {
191 192 193 194 195 196 197 198 199 200 201
		this.interceptorNames = interceptorNames;
	}

	/**
	 * Set whether the common interceptors should be applied before bean-specific ones.
	 * Default is "true"; else, bean-specific interceptors will get applied first.
	 */
	public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) {
		this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst;
	}

202
	@Override
203 204 205 206 207
	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
	}

	/**
J
Juergen Hoeller 已提交
208 209
	 * Return the owning {@link BeanFactory}.
	 * May be {@code null}, as this post-processor doesn't need to belong to a bean factory.
210 211 212 213 214 215
	 */
	protected BeanFactory getBeanFactory() {
		return this.beanFactory;
	}


216
	@Override
217
	public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
218 219 220
		if (this.proxyTypes.isEmpty()) {
			return null;
		}
221
		Object cacheKey = getCacheKey(beanClass, beanName);
222
		return this.proxyTypes.get(cacheKey);
223 224
	}

225
	@Override
226
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
227 228 229
		return null;
	}

230
	@Override
231 232
	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
233
		this.earlyProxyReferences.put(cacheKey, bean);
234 235 236
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

237
	@Override
238
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
239 240
		Object cacheKey = getCacheKey(beanClass, beanName);

241
		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
242
			if (this.advisedBeans.containsKey(cacheKey)) {
243 244
				return null;
			}
245
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
246
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
247 248 249 250 251 252 253
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
254 255 256
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
257
				this.targetSourcedBeans.add(beanName);
258 259 260 261 262
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
263 264 265 266 267
		}

		return null;
	}

268
	@Override
269 270 271 272
	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}

273
	@Override
274 275 276 277 278 279
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {

		return pvs;
	}

280
	@Override
281 282 283 284 285 286 287 288 289
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}

	/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
290
	@Override
291 292 293
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
294
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
295 296 297 298 299 300 301 302 303
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}


	/**
	 * Build a cache key for the given bean class and bean name.
304 305 306 307 308
	 * <p>Note: As of 4.2.3, this implementation does not return a concatenated
	 * class/name String anymore but rather the most efficient cache key possible:
	 * a plain bean name, prepended with {@link BeanFactory#FACTORY_BEAN_PREFIX}
	 * in case of a {@code FactoryBean}; or if no bean name specified, then the
	 * given bean {@code Class} as-is.
309 310 311 312
	 * @param beanClass the bean class
	 * @param beanName the bean name
	 * @return the cache key for the given class and name
	 */
313
	protected Object getCacheKey(Class<?> beanClass, String beanName) {
314 315 316 317 318 319 320
		if (StringUtils.hasLength(beanName)) {
			return (FactoryBean.class.isAssignableFrom(beanClass) ?
					BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
		}
		else {
			return beanClass;
		}
321 322 323 324 325 326 327 328 329 330
	}

	/**
	 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @param cacheKey the cache key for metadata access
	 * @return a proxy wrapping the bean, or the raw bean instance as-is
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
331
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
332 333
			return bean;
		}
334
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
335 336
			return bean;
		}
337
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
338
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
339 340 341 342 343 344
			return bean;
		}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
345
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
346 347
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
348 349 350 351
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

352
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
353 354 355 356 357 358
		return bean;
	}

	/**
	 * Return whether the given bean class represents an infrastructure class
	 * that should never be proxied.
359 360
	 * <p>The default implementation considers Advices, Advisors and
	 * AopInfrastructureBeans as infrastructure classes.
361 362
	 * @param beanClass the class of the bean
	 * @return whether the bean represents an infrastructure class
363
	 * @see org.aopalliance.aop.Advice
364
	 * @see org.springframework.aop.Advisor
365
	 * @see org.springframework.aop.framework.AopInfrastructureBean
366 367
	 * @see #shouldSkip
	 */
368
	protected boolean isInfrastructureClass(Class<?> beanClass) {
369
		boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
370
				Pointcut.class.isAssignableFrom(beanClass) ||
371
				Advisor.class.isAssignableFrom(beanClass) ||
372 373 374 375 376 377 378 379
				AopInfrastructureBean.class.isAssignableFrom(beanClass);
		if (retVal && logger.isTraceEnabled()) {
			logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
		}
		return retVal;
	}

	/**
380
	 * Subclasses should override this method to return {@code true} if the
381 382
	 * given bean should not be considered for auto-proxying by this post-processor.
	 * <p>Sometimes we need to be able to avoid this happening if it will lead to
383
	 * a circular reference. This implementation returns {@code false}.
384 385 386 387
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @return whether to skip the given bean
	 */
388
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
389 390 391 392 393
		return false;
	}

	/**
	 * Create a target source for bean instances. Uses any TargetSourceCreators if set.
394
	 * Returns {@code null} if no custom TargetSource should be used.
395 396 397 398 399 400 401
	 * <p>This implementation uses the "customTargetSourceCreators" property.
	 * Subclasses can override this method to use a different mechanism.
	 * @param beanClass the class of the bean to create a TargetSource for
	 * @param beanName the name of the bean
	 * @return a TargetSource for this bean
	 * @see #setCustomTargetSourceCreators
	 */
402
	protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
403 404 405
		// We can't create fancy target sources for directly registered singletons.
		if (this.customTargetSourceCreators != null &&
				this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
406
			for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
407 408 409 410 411
				TargetSource ts = tsc.getTargetSource(beanClass, beanName);
				if (ts != null) {
					// Found a matching TargetSource.
					if (logger.isDebugEnabled()) {
						logger.debug("TargetSourceCreator [" + tsc +
J
Juergen Hoeller 已提交
412
								"] found custom TargetSource for bean with name '" + beanName + "'");
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
					}
					return ts;
				}
			}
		}

		// No custom TargetSource found.
		return null;
	}

	/**
	 * Create an AOP proxy for the given bean.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @param targetSource the TargetSource for the proxy,
	 * already pre-configured to access the bean
	 * @return the AOP proxy for the bean
	 * @see #buildAdvisors
	 */
	protected Object createProxy(
435
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
436

437
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
438 439 440
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

441 442 443
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

444 445 446 447 448 449
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
450 451 452 453
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
454
		proxyFactory.addAdvisors(advisors);
455 456 457 458 459 460 461 462
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

463
		return proxyFactory.getProxy(getProxyClassLoader());
464 465 466
	}

	/**
467 468
	 * Determine whether the given bean should be proxied with its target class rather than its interfaces.
	 * <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
469 470 471 472 473 474
	 * of the corresponding bean definition.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @return whether the given bean should be proxied with its target class
	 * @see AutoProxyUtils#shouldProxyTargetClass
	 */
475
	protected boolean shouldProxyTargetClass(Class<?> beanClass, String beanName) {
476 477 478 479
		return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
				AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
	}

480 481 482 483
	/**
	 * Return whether the Advisors returned by the subclass are pre-filtered
	 * to match the bean's target class already, allowing the ClassFilter check
	 * to be skipped when building advisors chains for AOP invocations.
484
	 * <p>Default is {@code false}. Subclasses may override this if they
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
	 * will always return pre-filtered Advisors.
	 * @return whether the Advisors are pre-filtered
	 * @see #getAdvicesAndAdvisorsForBean
	 * @see org.springframework.aop.framework.Advised#setPreFiltered
	 */
	protected boolean advisorsPreFiltered() {
		return false;
	}

	/**
	 * Determine the advisors for the given bean, including the specific interceptors
	 * as well as the common interceptor, all adapted to the Advisor interface.
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @return the list of Advisors for the given bean
	 */
	protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
		// Handle prototypes correctly...
		Advisor[] commonInterceptors = resolveInterceptorNames();

506
		List<Object> allInterceptors = new ArrayList<Object>();
507 508
		if (specificInterceptors != null) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
509
			if (commonInterceptors.length > 0) {
510 511 512 513 514 515 516 517 518
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		if (logger.isDebugEnabled()) {
519
			int nrOfCommonInterceptors = commonInterceptors.length;
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
			int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
			logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
					" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
		}

		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

	/**
	 * Resolves the specified interceptor names to Advisor objects.
	 * @see #setInterceptorNames
	 */
	private Advisor[] resolveInterceptorNames() {
537 538
		ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory ?
				(ConfigurableBeanFactory) this.beanFactory : null);
539 540
		List<Advisor> advisors = new ArrayList<Advisor>();
		for (String beanName : this.interceptorNames) {
541 542 543 544 545
			if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
				Object next = this.beanFactory.getBean(beanName);
				advisors.add(this.advisorAdapterRegistry.wrap(next));
			}
		}
546
		return advisors.toArray(new Advisor[advisors.size()]);
547 548 549 550 551 552
	}

	/**
	 * Subclasses may choose to implement this: for example,
	 * to change the interfaces exposed.
	 * <p>The default implementation is empty.
J
Juergen Hoeller 已提交
553
	 * @param proxyFactory a ProxyFactory that is already configured with
554
	 * TargetSource and interfaces and will be used to create the proxy
555
	 * immediately after this method returns
556 557 558 559 560 561 562 563 564 565 566 567
	 */
	protected void customizeProxyFactory(ProxyFactory proxyFactory) {
	}


	/**
	 * Return whether the given bean is to be proxied, what additional
	 * advices (e.g. AOP Alliance interceptors) and advisors to apply.
	 * @param beanClass the class of the bean to advise
	 * @param beanName the name of the bean
	 * @param customTargetSource the TargetSource returned by the
	 * {@link #getCustomTargetSource} method: may be ignored.
568
	 * Will be {@code null} if no custom target source is in use.
569 570
	 * @return an array of additional interceptors for the particular bean;
	 * or an empty array if no additional interceptors but just the common ones;
571
	 * or {@code null} if no proxy at all, not even with the common interceptors.
572 573 574 575 576 577
	 * See constants DO_NOT_PROXY and PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS.
	 * @throws BeansException in case of errors
	 * @see #DO_NOT_PROXY
	 * @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
	 */
	protected abstract Object[] getAdvicesAndAdvisorsForBean(
578
			Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException;
579 580

}