Fix STS compatibility issues; other improvements

Revert changes to ParserContext, ReaderContext, and XmlReaderContext

    These changes cause cross-version incompatibilities at tooling time
    -- for instance, an STS version that ships with Spring 3.0.5
    classloads the ParserContext defined in that version, whereas it
    classloads NamespaceHandlers and BeanDefinitionParsers (by default)
    from the user application classpath, which may be building against
    3.1.0. If so, the changes introduced to these types in 3.1.0 are
    incompatible with expectations in the 3.0.5 world and cause all
    manner of problems.  In this case, it was NoSuchMethodError due to
    the newly-added XmlReaderContext.getProblemReporter() method; also
    IncompatibleClassChangeError due to the introduction of the
    ComponentRegistrar interface on ParserContext.

    Each of these problems have been mitigated, though the solutions
    are not ideal. The method mentioned has been removed, and instead
    the problemReporter field is now accessed reflectively.
    ParserContext now no longer implements ComponentRegistrar, and
    rather a ComponentRegistrarAdapter class has been introduced that
    passes method calls through to a ParserContext delegate.

Introduce AbstractSpecificationBeanDefinitionParser

    AbstractSpecificationBeanDefinitionParser has been introduced in
    order to improve the programming model for BeanDefinitionParsers
    that have been refactored to the new FeatureSpecification model.
    This new base class and it's template method implementation of
    parse/doParse ensure that common concerns like (1) adapting a
    ParserContext into a SpecificationContext, (2) setting source and
    source name on the specification, and (3) actually executing the
    specification are all managed by the base class.  The subclass
    implementation of doParse need only actually parse XML, populate
    and return the FeatureSpecification object.  This change removed
    the many duplicate 'createSpecificationContext' methods that had
    been lingering.

Minor improvement to BeanDefinitionReaderUtils API

    Introduced new BeanDefinitionReaderUtils#registerWithGeneratedName
    variant that accepts BeanDefinition as opposed to
    AbstractBeanDefinition, as BeanDefinition is all that is actually
    necessary to satisfy the needs of the method implementation. The
    latter variant accepting AbstractBeanDefinition has been deprecated
    but remains intact and delegates to the new variant in order to
    maintain binary compatibility.
This commit is contained in:
Chris Beams
2011-02-09 16:44:26 +00:00
parent 939da34869
commit 9cc125531b
20 changed files with 214 additions and 227 deletions

View File

@@ -1,25 +0,0 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.parsing;
import org.springframework.beans.factory.config.BeanDefinition;
public interface BeanDefinitionRegistrar {
String registerWithGeneratedName(BeanDefinition beanDefinition);
}

View File

@@ -16,9 +16,20 @@
package org.springframework.beans.factory.parsing;
public interface ComponentRegistrar extends BeanDefinitionRegistrar {
import org.springframework.beans.factory.config.BeanDefinition;
/**
* TODO SPR-7420: document
*
* @author Chris Beams
* @since 3.1
*/
public interface ComponentRegistrar {
String registerWithGeneratedName(BeanDefinition beanDefinition);
void registerBeanComponent(BeanComponentDefinition component);
void registerComponent(ComponentDefinition component);
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.parsing;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
/**
* TODO SPR-7420: document
* <p>Adapter is necessary as opposed to having ParserContext
* implement ComponentRegistrar directly due to tooling issues.
* STS may ship with a version of Spring older that 3.1 (when
* this type was introduced), and will run into
* IncompatibleClassChangeErrors when it's (3.0.5) ParserContext
* tries to mix with our (3.1.0) BeanDefinitionParser
* (and related) infrastructure.
*
* @author Chris Beams
* @since 3.1
*/
public class ComponentRegistrarAdapter implements ComponentRegistrar {
private final ParserContext parserContext;
public ComponentRegistrarAdapter(ParserContext parserContext) {
this.parserContext = parserContext;
}
public String registerWithGeneratedName(BeanDefinition beanDefinition) {
return this.parserContext.getReaderContext().registerWithGeneratedName(beanDefinition);
}
public void registerBeanComponent(BeanComponentDefinition component) {
this.parserContext.registerBeanComponent(component);
}
public void registerComponent(ComponentDefinition component) {
this.parserContext.registerComponent(component);
}
}

View File

@@ -30,13 +30,12 @@ public class ReaderContext {
private final Resource resource;
private final ProblemReporter problemReporter;
private final ReaderEventListener eventListener;
private final SourceExtractor sourceExtractor;
// TODO SPR-7420: review exposing problem reporter
protected final ProblemReporter problemReporter;
public ReaderContext(Resource resource, ProblemReporter problemReporter,
ReaderEventListener eventListener, SourceExtractor sourceExtractor) {

View File

@@ -166,12 +166,24 @@ public class BeanDefinitionReaderUtils {
* for the given bean definition or the definition cannot be registered
*/
public static String registerWithGeneratedName(
AbstractBeanDefinition definition, BeanDefinitionRegistry registry)
BeanDefinition definition, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
String generatedName = generateBeanName(definition, registry, false);
registry.registerBeanDefinition(generatedName, definition);
return generatedName;
}
/**
* @deprecated since Spring 3.1 in favor of
* {@link #registerWithGeneratedName(BeanDefinition, BeanDefinitionRegistry)}
* and its more general signature.
*/
@Deprecated
public static String registerWithGeneratedName(
AbstractBeanDefinition definition, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
return registerWithGeneratedName((BeanDefinition)definition, registry);
}
}

View File

@@ -21,7 +21,6 @@ import java.util.Stack;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.ComponentDefinition;
import org.springframework.beans.factory.parsing.ComponentRegistrar;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -37,7 +36,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
* @see XmlReaderContext
* @see BeanDefinitionParserDelegate
*/
public final class ParserContext implements ComponentRegistrar {
public final class ParserContext {
private final XmlReaderContext readerContext;
@@ -122,8 +121,4 @@ public final class ParserContext implements ComponentRegistrar {
registerComponent(component);
}
public String registerWithGeneratedName(BeanDefinition beanDefinition) {
return this.readerContext.registerWithGeneratedName(beanDefinition);
}
}

View File

@@ -83,9 +83,4 @@ public class XmlReaderContext extends ReaderContext {
return generatedName;
}
// TODO SPR-7420: review exposing problem reporter
public ProblemReporter getProblemReporter() {
return this.problemReporter;
}
}