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