001: /*
002: * Copyright 2002-2007 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: * http://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:
017: package org.springframework.beans.factory.wiring;
018:
019: import org.apache.commons.logging.Log;
020: import org.apache.commons.logging.LogFactory;
021:
022: import org.springframework.beans.factory.BeanFactory;
023: import org.springframework.beans.factory.BeanFactoryAware;
024: import org.springframework.beans.factory.DisposableBean;
025: import org.springframework.beans.factory.InitializingBean;
026: import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
027: import org.springframework.util.Assert;
028:
029: /**
030: * Convenient superclass for configurers that can perform Dependency Injection
031: * on objects (however they may be created).
032: *
033: * <p>Typically subclassed by AspectJ aspects.
034:
035: * <p>Subclasses may also need a metadata resolution strategy, in the
036: * {@link BeanWiringInfoResolver} interface. The default implementation looks
037: * for a bean with the same name as the fully-qualified class name. (This is
038: * the default name of the bean in a Spring XML file if the '<code>id</code>'
039: * attribute is not used.)
040:
041: * @author Rob Harrop
042: * @author Rod Johnson
043: * @author Juergen Hoeller
044: * @author Adrian Colyer
045: * @since 2.0
046: */
047: public abstract class BeanConfigurerSupport implements
048: BeanFactoryAware, InitializingBean, DisposableBean {
049:
050: /** Logger available to subclasses */
051: protected Log logger = LogFactory.getLog(getClass());
052:
053: private BeanWiringInfoResolver beanWiringInfoResolver;
054:
055: private AutowireCapableBeanFactory beanFactory;
056:
057: /**
058: * Set the <code>BeanWiringInfoResolver</code> to use.
059: * <p>Default behavior will be to look for a bean with the same name as the
060: * class.
061: * <p>As an alternative, consider using annotation-driven bean wiring.
062: * @param beanWiringInfoResolver the <code>BeanWiringInfoResolver</code> to use.
063: * @see ClassNameBeanWiringInfoResolver
064: * @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
065: */
066: public void setBeanWiringInfoResolver(
067: BeanWiringInfoResolver beanWiringInfoResolver) {
068: Assert.notNull(beanWiringInfoResolver,
069: "'beanWiringInfoResolver' cannot be null.");
070: this .beanWiringInfoResolver = beanWiringInfoResolver;
071: }
072:
073: /**
074: * Set the {@link BeanFactory} in which this aspect must configure beans.
075: * @throws IllegalArgumentException if the supplied <code>beanFactory</code> is
076: * not an {@link AutowireCapableBeanFactory}.
077: */
078: public void setBeanFactory(BeanFactory beanFactory) {
079: if (!(beanFactory instanceof AutowireCapableBeanFactory)) {
080: throw new IllegalArgumentException(
081: "Bean configurer aspect needs to run in an AutowireCapableBeanFactory, not in ["
082: + beanFactory + "]");
083: }
084: this .beanFactory = (AutowireCapableBeanFactory) beanFactory;
085: }
086:
087: /**
088: * If no {@link #setBeanWiringInfoResolver BeanWiringInfoResolver} was
089: * provided, use a {@link ClassNameBeanWiringInfoResolver} as the default.
090: */
091: public void afterPropertiesSet() throws Exception {
092: if (this .beanWiringInfoResolver == null) {
093: this .beanWiringInfoResolver = new ClassNameBeanWiringInfoResolver();
094: }
095: }
096:
097: /**
098: * Release references to the {@link BeanFactory} and
099: * {@link BeanWiringInfoResolver} when the container is destroyed.
100: */
101: public void destroy() {
102: this .beanFactory = null;
103: this .beanWiringInfoResolver = null;
104: }
105:
106: /**
107: * Configure the bean instance.
108: * <p>Subclasses can override this to provide custom configuration logic.
109: * Typically called by an aspect, for all bean instances matched by a
110: * pointcut.
111: * @param beanInstance the bean instance to configure (must <b>not</b> be <code>null</code>)
112: */
113: protected void configureBean(Object beanInstance) {
114: if (this .beanWiringInfoResolver == null) {
115: if (logger.isWarnEnabled()) {
116: logger
117: .warn("["
118: + getClass().getName()
119: + "] has not been configured by Spring "
120: + "and is unable to configure bean instances. Object with identity "
121: + "hashcode "
122: + System.identityHashCode(beanInstance)
123: + " has not been configured: "
124: + "Make sure this configurer runs in a Spring container. "
125: + "For example, add it to a Spring application context as an XML bean definition.");
126: }
127: return;
128: }
129:
130: BeanWiringInfo bwi = this .beanWiringInfoResolver
131: .resolveWiringInfo(beanInstance);
132: if (bwi == null) {
133: // Skip the bean if no wiring info given.
134: return;
135: }
136:
137: if (this .beanFactory == null) {
138: if (logger.isWarnEnabled()) {
139: logger
140: .warn("BeanFactory has not been set on ["
141: + getClass().getName()
142: + "]: "
143: + "Make sure this configurer runs in a Spring container. "
144: + "For example, add it to a Spring application context as an XML bean definition.");
145: }
146: return;
147: }
148:
149: if (bwi.indicatesAutowiring()) {
150: // Perform autowiring.
151: this .beanFactory.autowireBeanProperties(beanInstance, bwi
152: .getAutowireMode(), bwi.getDependencyCheck());
153: } else {
154: // Perform explicit wiring.
155: this.beanFactory.applyBeanPropertyValues(beanInstance, bwi
156: .getBeanName());
157: }
158: }
159:
160: }
|