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.support; 018 019import org.apache.commons.logging.Log; 020import org.apache.commons.logging.LogFactory; 021 022import org.springframework.beans.BeansException; 023import org.springframework.context.ApplicationContext; 024import org.springframework.context.ApplicationContextAware; 025import org.springframework.context.ApplicationContextException; 026 027/** 028 * Convenient superclass for application objects that want to be aware of 029 * the application context, e.g. for custom lookup of collaborating beans 030 * or for context-specific resource access. It saves the application 031 * context reference and provides an initialization callback method. 032 * Furthermore, it offers numerous convenience methods for message lookup. 033 * 034 * <p>There is no requirement to subclass this class: It just makes things 035 * a little easier if you need access to the context, e.g. for access to 036 * file resources or to the message source. Note that many application 037 * objects do not need to be aware of the application context at all, 038 * as they can receive collaborating beans via bean references. 039 * 040 * <p>Many framework classes are derived from this class, particularly 041 * within the web support. 042 * 043 * @author Rod Johnson 044 * @author Juergen Hoeller 045 * @see org.springframework.web.context.support.WebApplicationObjectSupport 046 */ 047public abstract class ApplicationObjectSupport implements ApplicationContextAware { 048 049 /** Logger that is available to subclasses */ 050 protected final Log logger = LogFactory.getLog(getClass()); 051 052 /** ApplicationContext this object runs in */ 053 private ApplicationContext applicationContext; 054 055 /** MessageSourceAccessor for easy message access */ 056 private MessageSourceAccessor messageSourceAccessor; 057 058 059 @Override 060 public final void setApplicationContext(ApplicationContext context) throws BeansException { 061 if (context == null && !isContextRequired()) { 062 // Reset internal context state. 063 this.applicationContext = null; 064 this.messageSourceAccessor = null; 065 } 066 else if (this.applicationContext == null) { 067 // Initialize with passed-in context. 068 if (!requiredContextClass().isInstance(context)) { 069 throw new ApplicationContextException( 070 "Invalid application context: needs to be of type [" + requiredContextClass().getName() + "]"); 071 } 072 this.applicationContext = context; 073 this.messageSourceAccessor = new MessageSourceAccessor(context); 074 initApplicationContext(context); 075 } 076 else { 077 // Ignore reinitialization if same context passed in. 078 if (this.applicationContext != context) { 079 throw new ApplicationContextException( 080 "Cannot reinitialize with different application context: current one is [" + 081 this.applicationContext + "], passed-in one is [" + context + "]"); 082 } 083 } 084 } 085 086 /** 087 * Determine whether this application object needs to run in an ApplicationContext. 088 * <p>Default is "false". Can be overridden to enforce running in a context 089 * (i.e. to throw IllegalStateException on accessors if outside a context). 090 * @see #getApplicationContext 091 * @see #getMessageSourceAccessor 092 */ 093 protected boolean isContextRequired() { 094 return false; 095 } 096 097 /** 098 * Determine the context class that any context passed to 099 * {@code setApplicationContext} must be an instance of. 100 * Can be overridden in subclasses. 101 * @see #setApplicationContext 102 */ 103 protected Class<?> requiredContextClass() { 104 return ApplicationContext.class; 105 } 106 107 /** 108 * Subclasses can override this for custom initialization behavior. 109 * Gets called by {@code setApplicationContext} after setting the context instance. 110 * <p>Note: Does </i>not</i> get called on reinitialization of the context 111 * but rather just on first initialization of this object's context reference. 112 * <p>The default implementation calls the overloaded {@link #initApplicationContext()} 113 * method without ApplicationContext reference. 114 * @param context the containing ApplicationContext 115 * @throws ApplicationContextException in case of initialization errors 116 * @throws BeansException if thrown by ApplicationContext methods 117 * @see #setApplicationContext 118 */ 119 protected void initApplicationContext(ApplicationContext context) throws BeansException { 120 initApplicationContext(); 121 } 122 123 /** 124 * Subclasses can override this for custom initialization behavior. 125 * <p>The default implementation is empty. Called by 126 * {@link #initApplicationContext(org.springframework.context.ApplicationContext)}. 127 * @throws ApplicationContextException in case of initialization errors 128 * @throws BeansException if thrown by ApplicationContext methods 129 * @see #setApplicationContext 130 */ 131 protected void initApplicationContext() throws BeansException { 132 } 133 134 135 /** 136 * Return the ApplicationContext that this object is associated with. 137 * @throws IllegalStateException if not running in an ApplicationContext 138 */ 139 public final ApplicationContext getApplicationContext() throws IllegalStateException { 140 if (this.applicationContext == null && isContextRequired()) { 141 throw new IllegalStateException( 142 "ApplicationObjectSupport instance [" + this + "] does not run in an ApplicationContext"); 143 } 144 return this.applicationContext; 145 } 146 147 /** 148 * Return a MessageSourceAccessor for the application context 149 * used by this object, for easy message access. 150 * @throws IllegalStateException if not running in an ApplicationContext 151 */ 152 protected final MessageSourceAccessor getMessageSourceAccessor() throws IllegalStateException { 153 if (this.messageSourceAccessor == null && isContextRequired()) { 154 throw new IllegalStateException( 155 "ApplicationObjectSupport instance [" + this + "] does not run in an ApplicationContext"); 156 } 157 return this.messageSourceAccessor; 158 } 159 160}