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