001/*
002 * Copyright 2002-2012 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.target;
018
019import org.apache.commons.logging.Log;
020import org.apache.commons.logging.LogFactory;
021
022import org.springframework.aop.TargetSource;
023
024/**
025 * {@link org.springframework.aop.TargetSource} implementation that will
026 * lazily create a user-managed object.
027 *
028 * <p>Creation of the lazy target object is controlled by the user by implementing
029 * the {@link #createObject()} method. This {@code TargetSource} will invoke
030 * this method the first time the proxy is accessed.
031 *
032 * <p>Useful when you need to pass a reference to some dependency to an object
033 * but you don't actually want the dependency to be created until it is first used.
034 * A typical scenario for this is a connection to a remote resource.
035 *
036 * @author Rob Harrop
037 * @author Juergen Hoeller
038 * @since 1.2.4
039 * @see #isInitialized()
040 * @see #createObject()
041 */
042public abstract class AbstractLazyCreationTargetSource implements TargetSource {
043
044        /** Logger available to subclasses */
045        protected final Log logger = LogFactory.getLog(getClass());
046
047        /** The lazily initialized target object */
048        private Object lazyTarget;
049
050
051        /**
052         * Return whether the lazy target object of this TargetSource
053         * has already been fetched.
054         */
055        public synchronized boolean isInitialized() {
056                return (this.lazyTarget != null);
057        }
058
059        /**
060         * This default implementation returns {@code null} if the
061         * target is {@code null} (it is hasn't yet been initialized),
062         * or the target class if the target has already been initialized.
063         * <p>Subclasses may wish to override this method in order to provide
064         * a meaningful value when the target is still {@code null}.
065         * @see #isInitialized()
066         */
067        @Override
068        public synchronized Class<?> getTargetClass() {
069                return (this.lazyTarget != null ? this.lazyTarget.getClass() : null);
070        }
071
072        @Override
073        public boolean isStatic() {
074                return false;
075        }
076
077        /**
078         * Returns the lazy-initialized target object,
079         * creating it on-the-fly if it doesn't exist already.
080         * @see #createObject()
081         */
082        @Override
083        public synchronized Object getTarget() throws Exception {
084                if (this.lazyTarget == null) {
085                        logger.debug("Initializing lazy target object");
086                        this.lazyTarget = createObject();
087                }
088                return this.lazyTarget;
089        }
090
091        @Override
092        public void releaseTarget(Object target) throws Exception {
093                // nothing to do
094        }
095
096
097        /**
098         * Subclasses should implement this method to return the lazy initialized object.
099         * Called the first time the proxy is invoked.
100         * @return the created object
101         * @throws Exception if creation failed
102         */
103        protected abstract Object createObject() throws Exception;
104
105}