001/*
002 * Copyright 2002-2016 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.aopalliance.intercept.Interceptor;
020
021import org.springframework.aop.TargetSource;
022import org.springframework.util.ClassUtils;
023
024/**
025 * Factory for AOP proxies for programmatic use, rather than via declarative
026 * setup in a bean factory. This class provides a simple way of obtaining
027 * and configuring AOP proxy instances in custom user code.
028 *
029 * @author Rod Johnson
030 * @author Juergen Hoeller
031 * @author Rob Harrop
032 * @since 14.03.2003
033 */
034@SuppressWarnings("serial")
035public class ProxyFactory extends ProxyCreatorSupport {
036
037        /**
038         * Create a new ProxyFactory.
039         */
040        public ProxyFactory() {
041        }
042
043        /**
044         * Create a new ProxyFactory.
045         * <p>Will proxy all interfaces that the given target implements.
046         * @param target the target object to be proxied
047         */
048        public ProxyFactory(Object target) {
049                setTarget(target);
050                setInterfaces(ClassUtils.getAllInterfaces(target));
051        }
052
053        /**
054         * Create a new ProxyFactory.
055         * <p>No target, only interfaces. Must add interceptors.
056         * @param proxyInterfaces the interfaces that the proxy should implement
057         */
058        public ProxyFactory(Class<?>... proxyInterfaces) {
059                setInterfaces(proxyInterfaces);
060        }
061
062        /**
063         * Create a new ProxyFactory for the given interface and interceptor.
064         * <p>Convenience method for creating a proxy for a single interceptor,
065         * assuming that the interceptor handles all calls itself rather than
066         * delegating to a target, like in the case of remoting proxies.
067         * @param proxyInterface the interface that the proxy should implement
068         * @param interceptor the interceptor that the proxy should invoke
069         */
070        public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
071                addInterface(proxyInterface);
072                addAdvice(interceptor);
073        }
074
075        /**
076         * Create a ProxyFactory for the specified {@code TargetSource},
077         * making the proxy implement the specified interface.
078         * @param proxyInterface the interface that the proxy should implement
079         * @param targetSource the TargetSource that the proxy should invoke
080         */
081        public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {
082                addInterface(proxyInterface);
083                setTargetSource(targetSource);
084        }
085
086
087        /**
088         * Create a new proxy according to the settings in this factory.
089         * <p>Can be called repeatedly. Effect will vary if we've added
090         * or removed interfaces. Can add and remove interceptors.
091         * <p>Uses a default class loader: Usually, the thread context class loader
092         * (if necessary for proxy creation).
093         * @return the proxy object
094         */
095        public Object getProxy() {
096                return createAopProxy().getProxy();
097        }
098
099        /**
100         * Create a new proxy according to the settings in this factory.
101         * <p>Can be called repeatedly. Effect will vary if we've added
102         * or removed interfaces. Can add and remove interceptors.
103         * <p>Uses the given class loader (if necessary for proxy creation).
104         * @param classLoader the class loader to create the proxy with
105         * (or {@code null} for the low-level proxy facility's default)
106         * @return the proxy object
107         */
108        public Object getProxy(ClassLoader classLoader) {
109                return createAopProxy().getProxy(classLoader);
110        }
111
112
113        /**
114         * Create a new proxy for the given interface and interceptor.
115         * <p>Convenience method for creating a proxy for a single interceptor,
116         * assuming that the interceptor handles all calls itself rather than
117         * delegating to a target, like in the case of remoting proxies.
118         * @param proxyInterface the interface that the proxy should implement
119         * @param interceptor the interceptor that the proxy should invoke
120         * @return the proxy object
121         * @see #ProxyFactory(Class, org.aopalliance.intercept.Interceptor)
122         */
123        @SuppressWarnings("unchecked")
124        public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
125                return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();
126        }
127
128        /**
129         * Create a proxy for the specified {@code TargetSource},
130         * implementing the specified interface.
131         * @param proxyInterface the interface that the proxy should implement
132         * @param targetSource the TargetSource that the proxy should invoke
133         * @return the proxy object
134         * @see #ProxyFactory(Class, org.springframework.aop.TargetSource)
135         */
136        @SuppressWarnings("unchecked")
137        public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
138                return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();
139        }
140
141        /**
142         * Create a proxy for the specified {@code TargetSource} that extends
143         * the target class of the {@code TargetSource}.
144         * @param targetSource the TargetSource that the proxy should invoke
145         * @return the proxy object
146         */
147        public static Object getProxy(TargetSource targetSource) {
148                if (targetSource.getTargetClass() == null) {
149                        throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
150                }
151                ProxyFactory proxyFactory = new ProxyFactory();
152                proxyFactory.setTargetSource(targetSource);
153                proxyFactory.setProxyTargetClass(true);
154                return proxyFactory.getProxy();
155        }
156
157}