001: /*
002: * Copyright 2002-2007 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: * http://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:
017: package org.springframework.aop.framework;
018:
019: import org.springframework.aop.TargetSource;
020: import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry;
021: import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
022: import org.springframework.aop.target.SingletonTargetSource;
023: import org.springframework.beans.factory.BeanClassLoaderAware;
024: import org.springframework.beans.factory.FactoryBean;
025: import org.springframework.beans.factory.FactoryBeanNotInitializedException;
026: import org.springframework.beans.factory.InitializingBean;
027: import org.springframework.util.ClassUtils;
028:
029: /**
030: * Convenient proxy factory bean superclass for proxy factory
031: * beans that create only singletons.
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: public abstract class AbstractSingletonProxyFactoryBean extends
041: ProxyConfig implements FactoryBean, BeanClassLoaderAware,
042: 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
054: .getInstance();
055:
056: private ClassLoader beanClassLoader = ClassUtils
057: .getDefaultClassLoader();
058:
059: private Object proxy;
060:
061: /**
062: * Set the target object, that is, the bean to be wrapped with a transactional proxy.
063: * <p>The target may be any object, in which case a SingletonTargetSource will
064: * be created. If it is a TargetSource, no wrapper TargetSource is created:
065: * This enables the use of a pooling or prototype TargetSource etc.
066: * @see org.springframework.aop.TargetSource
067: * @see org.springframework.aop.target.SingletonTargetSource
068: * @see org.springframework.aop.target.LazyInitTargetSource
069: * @see org.springframework.aop.target.PrototypeTargetSource
070: * @see org.springframework.aop.target.CommonsPoolTargetSource
071: */
072: public void setTarget(Object target) {
073: this .target = target;
074: }
075:
076: /**
077: * Specify the set of interfaces being proxied.
078: * <p>If not specified (the default), the AOP infrastructure works
079: * out which interfaces need proxying by analyzing the target,
080: * proxying all the interfaces that the target object implements.
081: */
082: public void setProxyInterfaces(Class[] proxyInterfaces) {
083: this .proxyInterfaces = proxyInterfaces;
084: }
085:
086: /**
087: * Set additional interceptors (or advisors) to be applied before the
088: * implicit transaction interceptor, e.g. PerformanceMonitorInterceptor.
089: * @see org.springframework.aop.interceptor.PerformanceMonitorInterceptor
090: */
091: public void setPreInterceptors(Object[] preInterceptors) {
092: this .preInterceptors = preInterceptors;
093: }
094:
095: /**
096: * Set additional interceptors (or advisors) to be applied after the
097: * implicit transaction interceptor, e.g. HibernateInterceptors for
098: * eagerly binding Sessions to the current thread when using JTA.
099: * <p>Note that this is just necessary if you rely on those interceptors in general:
100: * HibernateTemplate and JdoTemplate work nicely with JtaTransactionManager through
101: * implicit on-demand thread binding.
102: * @see org.springframework.orm.hibernate.HibernateInterceptor
103: * @see org.springframework.orm.jdo.JdoInterceptor
104: */
105: public void setPostInterceptors(Object[] postInterceptors) {
106: this .postInterceptors = postInterceptors;
107: }
108:
109: /**
110: * Specify the AdvisorAdapterRegistry to use.
111: * Default is the global AdvisorAdapterRegistry.
112: * @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry
113: */
114: public void setAdvisorAdapterRegistry(
115: AdvisorAdapterRegistry advisorAdapterRegistry) {
116: this .advisorAdapterRegistry = advisorAdapterRegistry;
117: }
118:
119: public void setBeanClassLoader(ClassLoader classLoader) {
120: this .beanClassLoader = classLoader;
121: }
122:
123: public void afterPropertiesSet() {
124: if (this .target == null) {
125: throw new IllegalArgumentException("'target' is required");
126: }
127: if (this .target instanceof String) {
128: throw new IllegalArgumentException(
129: "'target' needs to be a bean reference, not a bean name as value");
130: }
131:
132: ProxyFactory proxyFactory = new ProxyFactory();
133:
134: if (this .preInterceptors != null) {
135: for (int i = 0; i < this .preInterceptors.length; i++) {
136: proxyFactory.addAdvisor(this .advisorAdapterRegistry
137: .wrap(this .preInterceptors[i]));
138: }
139: }
140:
141: // Add the main interceptor (typically an Advisor).
142: proxyFactory.addAdvisor(this .advisorAdapterRegistry
143: .wrap(createMainInterceptor()));
144:
145: if (this .postInterceptors != null) {
146: for (int i = 0; i < this .postInterceptors.length; i++) {
147: proxyFactory.addAdvisor(this .advisorAdapterRegistry
148: .wrap(this .postInterceptors[i]));
149: }
150: }
151:
152: proxyFactory.copyFrom(this );
153:
154: TargetSource targetSource = createTargetSource(this .target);
155: proxyFactory.setTargetSource(targetSource);
156:
157: if (this .proxyInterfaces != null) {
158: proxyFactory.setInterfaces(this .proxyInterfaces);
159: } else if (!isProxyTargetClass()) {
160: // Rely on AOP infrastructure to tell us what interfaces to proxy.
161: proxyFactory.setInterfaces(ClassUtils
162: .getAllInterfacesForClass(targetSource
163: .getTargetClass()));
164: }
165:
166: this .proxy = getProxy(proxyFactory);
167: }
168:
169: /**
170: * Determine a TargetSource for the given target (or TargetSource).
171: * @param target target. If this is an implementation of TargetSource it is
172: * used as our TargetSource; otherwise it is wrapped in a SingletonTargetSource.
173: * @return a TargetSource for this object
174: */
175: protected TargetSource createTargetSource(Object target) {
176: if (target instanceof TargetSource) {
177: return (TargetSource) target;
178: } else {
179: return new SingletonTargetSource(target);
180: }
181: }
182:
183: /**
184: * Return the proxy object to expose.
185: * <p>The default implementation uses a <code>getProxy</code> call with
186: * the factory's bean class loader. Can be overridden to specify a
187: * custom class loader.
188: * @param aopProxy the prepared AopProxy instance to get the proxy from
189: * @return the proxy object to expose
190: * @see AopProxy#getProxy(ClassLoader)
191: */
192: protected Object getProxy(AopProxy aopProxy) {
193: return aopProxy.getProxy(this .beanClassLoader);
194: }
195:
196: public Object getObject() {
197: if (this .proxy == null) {
198: throw new FactoryBeanNotInitializedException();
199: }
200: return this .proxy;
201: }
202:
203: public Class getObjectType() {
204: if (this .proxy != null) {
205: return this .proxy.getClass();
206: }
207: if (this .proxyInterfaces != null
208: && this .proxyInterfaces.length == 1) {
209: return this .proxyInterfaces[0];
210: }
211: if (this .target instanceof TargetSource) {
212: return ((TargetSource) this .target).getTargetClass();
213: }
214: if (this .target != null) {
215: return this .target.getClass();
216: }
217: return null;
218: }
219:
220: public final boolean isSingleton() {
221: return true;
222: }
223:
224: /**
225: * Create the "main" interceptor for this proxy factory bean.
226: * Typically an Advisor, but can also be any type of Advice.
227: * <p>Pre-interceptors will be applied before, post-interceptors
228: * will be applied after this interceptor.
229: */
230: protected abstract Object createMainInterceptor();
231:
232: }
|