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.context.access;
018
019import org.springframework.beans.factory.BeanFactory;
020import org.springframework.beans.factory.access.BeanFactoryReference;
021import org.springframework.context.ApplicationContext;
022import org.springframework.context.ConfigurableApplicationContext;
023
024/**
025 * ApplicationContext-specific implementation of BeanFactoryReference,
026 * wrapping a newly created ApplicationContext, closing it on release.
027 *
028 * <p>As per BeanFactoryReference contract, {@code release} may be called
029 * more than once, with subsequent calls not doing anything. However, calling
030 * {@code getFactory} after a {@code release} call will cause an exception.
031 *
032 * @author Juergen Hoeller
033 * @author Colin Sampaleanu
034 * @since 13.02.2004
035 * @see org.springframework.context.ConfigurableApplicationContext#close
036 */
037public class ContextBeanFactoryReference implements BeanFactoryReference {
038
039        private ApplicationContext applicationContext;
040
041
042        /**
043         * Create a new ContextBeanFactoryReference for the given context.
044         * @param applicationContext the ApplicationContext to wrap
045         */
046        public ContextBeanFactoryReference(ApplicationContext applicationContext) {
047                this.applicationContext = applicationContext;
048        }
049
050
051        @Override
052        public BeanFactory getFactory() {
053                if (this.applicationContext == null) {
054                        throw new IllegalStateException(
055                                        "ApplicationContext owned by this BeanFactoryReference has been released");
056                }
057                return this.applicationContext;
058        }
059
060        @Override
061        public void release() {
062                if (this.applicationContext != null) {
063                        ApplicationContext savedCtx;
064
065                        // We don't actually guarantee thread-safety, but it's not a lot of extra work.
066                        synchronized (this) {
067                                savedCtx = this.applicationContext;
068                                this.applicationContext = null;
069                        }
070
071                        if (savedCtx != null && savedCtx instanceof ConfigurableApplicationContext) {
072                                ((ConfigurableApplicationContext) savedCtx).close();
073                        }
074                }
075        }
076
077}