📄 abstractautoproxycreator.java
字号:
return pvs;
}
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
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (this.targetSourcedBeans.contains(beanName)) {
return bean;
}
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.nonAdvisedBeans.contains(cacheKey)) {
return bean;
}
if (isInfrastructureClass(bean.getClass(), beanName) || shouldSkip(bean.getClass(), beanName)) {
this.nonAdvisedBeans.add(cacheKey);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.add(cacheKey);
return createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
}
this.nonAdvisedBeans.add(cacheKey);
return bean;
}
/**
* Build a cache key for the given bean class and bean name.
* @param beanClass the bean class
* @param beanName the bean name
* @return the cache key for the given class and name
*/
protected Object getCacheKey(Class beanClass, String beanName) {
return beanClass.getName() + "_" + beanName;
}
/**
* Return whether the given bean class and bean name represents an
* infrastructure class that should never be proxied.
* @deprecated in favor of <code>isInfrastructureClass(beanClass)</code>
* @see #isInfrastructureClass(Class)
*/
protected boolean isInfrastructureClass(Class beanClass, String beanName) {
return isInfrastructureClass(beanClass);
}
/**
* Return whether the given bean class represents an infrastructure class
* that should never be proxied.
* <p>Default implementation considers Advisors, Advices and
* AbstractAutoProxyCreators as infrastructure classes.
* @param beanClass the class of the bean
* @return whether the bean represents an infrastructure class
* @see org.springframework.aop.Advisor
* @see org.aopalliance.intercept.MethodInterceptor
* @see #shouldSkip
*/
protected boolean isInfrastructureClass(Class beanClass) {
boolean retVal = Advisor.class.isAssignableFrom(beanClass) ||
Advice.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
/**
* Subclasses should override this method to return <code>true</code> if the
* 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
* a circular reference. This implementation returns <code>false</code>.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @return whether to skip the given bean
*/
protected boolean shouldSkip(Class beanClass, String beanName) {
return false;
}
/**
* Create a target source for bean instances. Uses any TargetSourceCreators if set.
* Returns <code>null</code> if no custom TargetSource should be used.
* <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
*/
protected TargetSource getCustomTargetSource(Class beanClass, String beanName) {
// We can't create fancy target sources for directly registered singletons.
if (this.customTargetSourceCreators != null &&
this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
for (int i = 0; i < this.customTargetSourceCreators.length; i++) {
TargetSourceCreator tsc = this.customTargetSourceCreators[i];
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
if (ts != null) {
// Found a matching TargetSource.
if (logger.isDebugEnabled()) {
logger.debug("TargetSourceCreator [" + tsc +
" found custom TargetSource for bean with name '" + beanName + "'");
}
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(
Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);
if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass);
for (int i = 0; i < targetInterfaces.length; i++) {
proxyFactory.addInterface(targetInterfaces[i]);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (int i = 0; i < advisors.length; i++) {
proxyFactory.addAdvisor(advisors[i]);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
return proxyFactory.getProxy(this.beanClassLoader);
}
/**
* Determine whether the given bean should be proxied with its target
* class rather than its interfaces. Checks the
* {@link #setProxyTargetClass "proxyTargetClass" setting} as well as the
* {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
* 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
*/
protected boolean shouldProxyTargetClass(Class beanClass, String beanName) {
return (isProxyTargetClass() ||
(this.beanFactory instanceof ConfigurableListableBeanFactory &&
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName)));
}
/**
* 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();
List allInterceptors = new ArrayList();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors != null) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isDebugEnabled()) {
int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
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() {
ConfigurableBeanFactory cbf =
(this.beanFactory instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) this.beanFactory : null);
List advisors = new ArrayList();
for (int i = 0; i < this.interceptorNames.length; i++) {
String beanName = this.interceptorNames[i];
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Object next = this.beanFactory.getBean(beanName);
advisors.add(this.advisorAdapterRegistry.wrap(next));
}
}
return (Advisor[]) advisors.toArray(new Advisor[advisors.size()]);
}
/**
* Subclasses may choose to implement this: for example,
* to change the interfaces exposed.
* <p>The default implementation is empty.
* @param proxyFactory ProxyFactory that is already configured with
* TargetSource and interfaces and will be used to create the proxy
* immediably after this method returns
*/
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.
* Will be <code>null</code> if no custom target source is in use.
* @return an array of additional interceptors for the particular bean;
* or an empty array if no additional interceptors but just the common ones;
* or <code>null</code> if no proxy at all, not even with the common interceptors.
* 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(
Class beanClass, String beanName, TargetSource customTargetSource) throws BeansException;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -