001/* 002 * Copyright 2002-2015 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.aop.TargetSource; 020import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry; 021import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry; 022import org.springframework.aop.target.SingletonTargetSource; 023import org.springframework.beans.factory.BeanClassLoaderAware; 024import org.springframework.beans.factory.FactoryBean; 025import org.springframework.beans.factory.FactoryBeanNotInitializedException; 026import org.springframework.beans.factory.InitializingBean; 027import org.springframework.util.ClassUtils; 028 029/** 030 * Convenient superclass for {@link FactoryBean} types that produce singleton-scoped 031 * proxy objects. 032 * 033 * <p>Manages pre- and post-interceptors (references, rather than 034 * interceptor names, as in {@link ProxyFactoryBean}) and provides 035 * consistent interface management. 036 * 037 * @author Juergen Hoeller 038 * @since 2.0 039 */ 040@SuppressWarnings("serial") 041public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig 042 implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean { 043 044 private Object target; 045 046 private Class<?>[] proxyInterfaces; 047 048 private Object[] preInterceptors; 049 050 private Object[] postInterceptors; 051 052 /** Default is global AdvisorAdapterRegistry */ 053 private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance(); 054 055 private transient ClassLoader proxyClassLoader; 056 057 private Object proxy; 058 059 060 /** 061 * Set the target object, that is, the bean to be wrapped with a transactional proxy. 062 * <p>The target may be any object, in which case a SingletonTargetSource will 063 * be created. If it is a TargetSource, no wrapper TargetSource is created: 064 * This enables the use of a pooling or prototype TargetSource etc. 065 * @see org.springframework.aop.TargetSource 066 * @see org.springframework.aop.target.SingletonTargetSource 067 * @see org.springframework.aop.target.LazyInitTargetSource 068 * @see org.springframework.aop.target.PrototypeTargetSource 069 * @see org.springframework.aop.target.CommonsPool2TargetSource 070 */ 071 public void setTarget(Object target) { 072 this.target = target; 073 } 074 075 /** 076 * Specify the set of interfaces being proxied. 077 * <p>If not specified (the default), the AOP infrastructure works 078 * out which interfaces need proxying by analyzing the target, 079 * proxying all the interfaces that the target object implements. 080 */ 081 public void setProxyInterfaces(Class<?>[] proxyInterfaces) { 082 this.proxyInterfaces = proxyInterfaces; 083 } 084 085 /** 086 * Set additional interceptors (or advisors) to be applied before the 087 * implicit transaction interceptor, e.g. a PerformanceMonitorInterceptor. 088 * <p>You may specify any AOP Alliance MethodInterceptors or other 089 * Spring AOP Advices, as well as Spring AOP Advisors. 090 * @see org.springframework.aop.interceptor.PerformanceMonitorInterceptor 091 */ 092 public void setPreInterceptors(Object[] preInterceptors) { 093 this.preInterceptors = preInterceptors; 094 } 095 096 /** 097 * Set additional interceptors (or advisors) to be applied after the 098 * implicit transaction interceptor. 099 * <p>You may specify any AOP Alliance MethodInterceptors or other 100 * Spring AOP Advices, as well as Spring AOP Advisors. 101 */ 102 public void setPostInterceptors(Object[] postInterceptors) { 103 this.postInterceptors = postInterceptors; 104 } 105 106 /** 107 * Specify the AdvisorAdapterRegistry to use. 108 * Default is the global AdvisorAdapterRegistry. 109 * @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry 110 */ 111 public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) { 112 this.advisorAdapterRegistry = advisorAdapterRegistry; 113 } 114 115 /** 116 * Set the ClassLoader to generate the proxy class in. 117 * <p>Default is the bean ClassLoader, i.e. the ClassLoader used by the 118 * containing BeanFactory for loading all bean classes. This can be 119 * overridden here for specific proxies. 120 */ 121 public void setProxyClassLoader(ClassLoader classLoader) { 122 this.proxyClassLoader = classLoader; 123 } 124 125 @Override 126 public void setBeanClassLoader(ClassLoader classLoader) { 127 if (this.proxyClassLoader == null) { 128 this.proxyClassLoader = classLoader; 129 } 130 } 131 132 133 @Override 134 public void afterPropertiesSet() { 135 if (this.target == null) { 136 throw new IllegalArgumentException("Property 'target' is required"); 137 } 138 if (this.target instanceof String) { 139 throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value"); 140 } 141 if (this.proxyClassLoader == null) { 142 this.proxyClassLoader = ClassUtils.getDefaultClassLoader(); 143 } 144 145 ProxyFactory proxyFactory = new ProxyFactory(); 146 147 if (this.preInterceptors != null) { 148 for (Object interceptor : this.preInterceptors) { 149 proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); 150 } 151 } 152 153 // Add the main interceptor (typically an Advisor). 154 proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor())); 155 156 if (this.postInterceptors != null) { 157 for (Object interceptor : this.postInterceptors) { 158 proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); 159 } 160 } 161 162 proxyFactory.copyFrom(this); 163 164 TargetSource targetSource = createTargetSource(this.target); 165 proxyFactory.setTargetSource(targetSource); 166 167 if (this.proxyInterfaces != null) { 168 proxyFactory.setInterfaces(this.proxyInterfaces); 169 } 170 else if (!isProxyTargetClass()) { 171 // Rely on AOP infrastructure to tell us what interfaces to proxy. 172 proxyFactory.setInterfaces( 173 ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader)); 174 } 175 176 postProcessProxyFactory(proxyFactory); 177 178 this.proxy = proxyFactory.getProxy(this.proxyClassLoader); 179 } 180 181 /** 182 * Determine a TargetSource for the given target (or TargetSource). 183 * @param target target. If this is an implementation of TargetSource it is 184 * used as our TargetSource; otherwise it is wrapped in a SingletonTargetSource. 185 * @return a TargetSource for this object 186 */ 187 protected TargetSource createTargetSource(Object target) { 188 if (target instanceof TargetSource) { 189 return (TargetSource) target; 190 } 191 else { 192 return new SingletonTargetSource(target); 193 } 194 } 195 196 /** 197 * A hook for subclasses to post-process the {@link ProxyFactory} 198 * before creating the proxy instance with it. 199 * @param proxyFactory the AOP ProxyFactory about to be used 200 * @since 4.2 201 */ 202 protected void postProcessProxyFactory(ProxyFactory proxyFactory) { 203 } 204 205 206 @Override 207 public Object getObject() { 208 if (this.proxy == null) { 209 throw new FactoryBeanNotInitializedException(); 210 } 211 return this.proxy; 212 } 213 214 @Override 215 public Class<?> getObjectType() { 216 if (this.proxy != null) { 217 return this.proxy.getClass(); 218 } 219 if (this.proxyInterfaces != null && this.proxyInterfaces.length == 1) { 220 return this.proxyInterfaces[0]; 221 } 222 if (this.target instanceof TargetSource) { 223 return ((TargetSource) this.target).getTargetClass(); 224 } 225 if (this.target != null) { 226 return this.target.getClass(); 227 } 228 return null; 229 } 230 231 @Override 232 public final boolean isSingleton() { 233 return true; 234 } 235 236 237 /** 238 * Create the "main" interceptor for this proxy factory bean. 239 * Typically an Advisor, but can also be any type of Advice. 240 * <p>Pre-interceptors will be applied before, post-interceptors 241 * will be applied after this interceptor. 242 */ 243 protected abstract Object createMainInterceptor(); 244 245}