提交 6deb1aca 编写于 作者: C Chris Beams

Refactoring and repackaging

上级 d4fdad22
......@@ -67,8 +67,7 @@ import org.springframework.config.java.Validator;
@Documented
@Factory(registrarType=BeanRegistrar.class,
callbackType=BeanMethodInterceptor.class,
validatorTypes={BeanValidator.class,
IllegalBeanOverrideValidator.class})
validatorTypes={BeanValidator.class, IllegalBeanOverrideValidator.class})
public @interface Bean {
/**
......
......@@ -15,23 +15,17 @@
*/
package org.springframework.config.java.internal.factory.support;
import static org.springframework.config.java.Util.*;
import java.util.ArrayList;
import java.util.Map;
import org.objectweb.asm.ClassReader;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.config.java.Configuration;
import org.springframework.config.java.ConfigurationModel;
import org.springframework.config.java.MalformedJavaConfigurationException;
import org.springframework.config.java.UsageError;
import org.springframework.config.java.internal.parsing.ConfigurationParser;
import org.springframework.config.java.internal.parsing.asm.AsmConfigurationParser;
import org.springframework.config.java.internal.parsing.asm.AsmUtils;
import org.springframework.core.io.ClassPathResource;
......@@ -44,17 +38,17 @@ import org.springframework.core.io.ClassPathResource;
*
* @author Chris Beams
*/
public class AsmJavaConfigBeanDefinitionReader {
public class ConfigurationClassBeanDefinitionReader {
private final ConfigurationModelBeanDefinitionReader modelBeanDefinitionReader;
/**
* Creates a new {@link AsmJavaConfigBeanDefinitionReader}.
* Creates a new {@link ConfigurationClassBeanDefinitionReader}.
*
* @param registry {@link BeanDefinitionRegistry} into which new bean definitions will be
* @param beanFactory {@link DefaultListableBeanFactory} into which new bean definitions will be
* registered as they are read from Configuration classes.
*/
public AsmJavaConfigBeanDefinitionReader(DefaultListableBeanFactory beanFactory) {
public ConfigurationClassBeanDefinitionReader(DefaultListableBeanFactory beanFactory) {
this.modelBeanDefinitionReader = new ConfigurationModelBeanDefinitionReader(beanFactory);
}
......@@ -64,13 +58,10 @@ public class AsmJavaConfigBeanDefinitionReader {
* supplied during construction.
*/
public int loadBeanDefinitions(ConfigurationModel model, Map<String, ClassPathResource> configClassResources) throws BeanDefinitionStoreException {
ConfigurationParser parser = new AsmConfigurationParser(model);
ConfigurationParser parser = new ConfigurationParser(model);
for (String id : configClassResources.keySet()) {
String resourcePath = configClassResources.get(id).getPath();
ClassReader configClassReader = AsmUtils.newClassReader(getClassAsStream(resourcePath));
parser.parse(configClassReader, id);
}
for (String id : configClassResources.keySet())
parser.parse(configClassResources.get(id), id);
ArrayList<UsageError> errors = new ArrayList<UsageError>();
model.validate(errors);
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import org.objectweb.asm.AnnotationVisitor;
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import java.io.IOException;
import java.io.InputStream;
......
......@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import static org.springframework.config.java.Util.*;
import static org.springframework.config.java.internal.parsing.asm.AsmUtils.*;
import static org.springframework.config.java.internal.parsing.asm.MutableAnnotationUtils.*;
import static org.springframework.config.java.internal.parsing.AsmUtils.*;
import static org.springframework.config.java.internal.parsing.MutableAnnotationUtils.*;
import static org.springframework.util.ClassUtils.*;
import java.lang.annotation.Annotation;
......
......@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import static org.springframework.config.java.Util.*;
import static org.springframework.config.java.internal.parsing.asm.MutableAnnotationUtils.*;
import static org.springframework.config.java.internal.parsing.MutableAnnotationUtils.*;
import static org.springframework.util.ClassUtils.*;
import java.lang.annotation.Annotation;
......
......@@ -15,46 +15,65 @@
*/
package org.springframework.config.java.internal.parsing;
import org.objectweb.asm.ClassReader;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.config.java.Configuration;
import org.springframework.config.java.ConfigurationClass;
import org.springframework.config.java.ConfigurationModel;
import org.springframework.config.java.Util;
import org.springframework.core.io.ClassPathResource;
/**
* Parses a {@link Configuration} class definition, usually into a {@link ConfigurationModel}.
* Parses a {@link Configuration} class definition, populating a {@link ConfigurationModel}.
* This ASM-based implementation avoids reflection and eager classloading in order to
* interoperate effectively with tooling (Spring IDE) and OSGi environments.
* <p>
* This interface aids in separating the process of reading a class file (via reflection, ASM, etc)
* from the process of registering bean definitions based on the content of that class.
* This class helps separate the concern of parsing the structure of a Configuration class
* from the concern of registering {@link BeanDefinition} objects based on the content of
* that model.
*
* @see org.springframework.config.java.internal.parsing.asm.AsmConfigurationParser
* @see org.springframework.config.java.ConfigurationModel
* @see org.springframework.config.java.internal.factory.support.ConfigurationModelBeanDefinitionReader
*
*
* @author Chris Beams
*/
public interface ConfigurationParser {
*/
public class ConfigurationParser {
/**
* Parse the Configuration object represented by <var>configurationSource.</var>
*
* @param configurationSource representation of a Configuration class, may be java.lang.Class,
* ASM representation or otherwise
*
* @see org.springframework.config.java.Configuration
* Model to be populated during calls to {@link #parse(Object, String)}
*/
void parse(Object configurationSource);
private final ConfigurationModel model;
/**
* Optionally propagate a custom name for this <var>configurationSource</var>. Usually this id
* corresponds to the name of a Configuration bean as declared in a beans XML.
* Creates a new parser instance that will be used to populate <var>model</var>.
*
* @param configurationSource representation of a Configuration class, may be java.lang.Class,
* ASM representation or otherwise
* @param configurationId name of this configuration class, probably corresponding to a
* bean id
* @param model model to be populated by each successive call to {@link #parse(Object, String)}
*/
public ConfigurationParser(ConfigurationModel model) {
this.model = model;
}
/**
* Parse the {@link Configuration @Configuration} class encapsulated by
* <var>configurationSource</var>.
*
* @see org.springframework.config.java.Configuration
* @see org.springframework.config.java.process.ConfigurationPostProcessor
* @param configurationSource reader for Configuration class being parsed
* @param configurationId may be null, but if populated represents the bean id
* (assumes that this configuration class was configured via XML)
*/
void parse(Object configurationSource, String configurationId);
public void parse(ClassPathResource resource, String configurationId) {
String resourcePath = resource.getPath();
ClassReader configClassReader = AsmUtils.newClassReader(Util.getClassAsStream(resourcePath));
ConfigurationClass configClass = new ConfigurationClass();
configClass.setBeanName(configurationId);
configClassReader.accept(new ConfigurationClassVisitor(configClass, model), false);
model.add(configClass);
}
}
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
/**
......
......@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import static org.springframework.config.java.Util.*;
import static org.springframework.config.java.internal.parsing.asm.MutableAnnotationUtils.*;
import static org.springframework.config.java.internal.parsing.MutableAnnotationUtils.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import static java.lang.String.*;
import static org.springframework.core.annotation.AnnotationUtils.*;
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
......
......@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.config.java.internal.parsing.asm;
package org.springframework.config.java.internal.parsing;
import static org.springframework.config.java.Util.*;
import static org.springframework.config.java.internal.parsing.asm.MutableAnnotationUtils.*;
import static org.springframework.config.java.internal.parsing.MutableAnnotationUtils.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
......
/*
* Copyright 2002-2008 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.config.java.internal.parsing.asm;
import org.objectweb.asm.ClassReader;
import org.springframework.config.java.Configuration;
import org.springframework.config.java.ConfigurationClass;
import org.springframework.config.java.ConfigurationModel;
import org.springframework.config.java.internal.parsing.ConfigurationParser;
import org.springframework.util.Assert;
/**
* ASM-based implementation of {@link ConfigurationParser}. Avoids reflection and eager classloading
* in order to interoperate effectively with tooling (Spring IDE).
*
* @see org.springframework.config.java.model.AsmConfigurationParserTests
* @author Chris Beams
*/
public class AsmConfigurationParser implements ConfigurationParser {
/**
* Model to be populated during calls to {@link #parse(Object)}
*/
private final ConfigurationModel model;
/**
* Creates a new parser instance that will be used to populate <var>model</var>.
*
* @param model model to be populated by each successive call to {@link #parse(Object)}
*/
public AsmConfigurationParser(ConfigurationModel model) {
this.model = model;
}
/**
* Convenience implementation, delegates to {@link #parse(Object, String)},
* passing in {@code null} for the configurationId.
*
* @param configurationSource must be an ASM {@link ClassReader}
*/
public void parse(Object configurationSource) {
parse(configurationSource, null);
}
/**
* Parse the {@link Configuration @Configuration} class encapsulated by
* <var>configurationSource</var>.
*
* @param configurationSource must be an ASM {@link ClassReader}
* @param configurationId may be null, but if populated represents the bean id
* (assumes that this configuration class was configured via XML)
*/
public void parse(Object configurationSource, String configurationId) {
Assert.isInstanceOf(ClassReader.class, configurationSource,
"configurationSource must be an ASM ClassReader");
ConfigurationClass configClass = new ConfigurationClass();
configClass.setBeanName(configurationId);
parse((ClassReader) configurationSource, configClass);
}
/**
* Kicks off visiting <var>configClass</var> with {@link ConfigurationClassVisitor}
*/
private void parse(ClassReader reader, ConfigurationClass configClass) {
reader.accept(new ConfigurationClassVisitor(configClass, model), false);
model.add(configClass);
}
}
......@@ -17,6 +17,7 @@ package org.springframework.config.java.internal.process;
import static org.springframework.config.java.Util.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import org.apache.commons.logging.Log;
......@@ -29,8 +30,12 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.config.java.Configuration;
import org.springframework.config.java.ConfigurationModel;
import org.springframework.config.java.MalformedJavaConfigurationException;
import org.springframework.config.java.UsageError;
import org.springframework.config.java.internal.enhancement.ConfigurationEnhancer;
import org.springframework.config.java.internal.factory.support.AsmJavaConfigBeanDefinitionReader;
import org.springframework.config.java.internal.factory.support.ConfigurationClassBeanDefinitionReader;
import org.springframework.config.java.internal.factory.support.ConfigurationModelBeanDefinitionReader;
import org.springframework.config.java.internal.parsing.ConfigurationParser;
import org.springframework.config.java.process.ConfigurationPostProcessor;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ClassUtils;
......@@ -46,19 +51,21 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
* to parse and enhance them. Also registers any {@link BeanPostProcessor} objects
* necessary to fulfill JavaConfig requirements.
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if(!(beanFactory instanceof DefaultListableBeanFactory))
public void postProcessBeanFactory(ConfigurableListableBeanFactory clBeanFactory) throws BeansException {
if(!(clBeanFactory instanceof DefaultListableBeanFactory))
throw new IllegalStateException("beanFactory must be of type "
+ DefaultListableBeanFactory.class.getSimpleName());
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) clBeanFactory;
ConfigurationModel model = new ConfigurationModel();
parseAnyConfigurationClasses(beanFactory, model);
enhanceAnyConfigurationClasses((DefaultListableBeanFactory) beanFactory, model);
enhanceAnyConfigurationClasses(beanFactory, model);
}
private void parseAnyConfigurationClasses(ConfigurableListableBeanFactory beanFactory, ConfigurationModel model) {
private void parseAnyConfigurationClasses(DefaultListableBeanFactory beanFactory, ConfigurationModel model) {
// linked map is important for maintaining predictable ordering of configuration classes.
// this is important in bean / value override situations.
......@@ -75,7 +82,18 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
}
}
beanDefinitionReader(beanFactory).loadBeanDefinitions(model, configClassResources);
ConfigurationModelBeanDefinitionReader modelBeanDefinitionReader = new ConfigurationModelBeanDefinitionReader(beanFactory);
ConfigurationParser parser = new ConfigurationParser(model);
for (String id : configClassResources.keySet())
parser.parse(configClassResources.get(id), id);
ArrayList<UsageError> errors = new ArrayList<UsageError>();
model.validate(errors);
if (errors.size() > 0)
throw new MalformedJavaConfigurationException(errors.toArray(new UsageError[] { }));
modelBeanDefinitionReader.loadBeanDefinitions(model);
}
/**
......@@ -96,7 +114,6 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// is the beanDef marked as representing a configuration class?
if (!isConfigClass(beanDef))
continue;
......@@ -117,15 +134,6 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
logger.warn("Found no @Configuration class BeanDefinitions within " + beanFactory);
}
private AsmJavaConfigBeanDefinitionReader beanDefinitionReader(ConfigurableListableBeanFactory beanFactory) {
// reader requires DefaultListableBeanFactory for it's registerBeanDefinition() method
if(!(beanFactory instanceof DefaultListableBeanFactory))
throw new IllegalStateException("beanFactory must be of type "
+ DefaultListableBeanFactory.class.getSimpleName());
return new AsmJavaConfigBeanDefinitionReader((DefaultListableBeanFactory)beanFactory);
}
/**
* Determines whether the class for <var>beanDef</var> is a {@link Configuration}-annotated
* class. Returns false if <var>beanDef</var> has no class specified.
......@@ -133,7 +141,7 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
* Note: the classloading used within should not be problematic or interfere with tooling in any
* way. BeanFactoryPostProcessing happens only during actual runtime processing via
* {@link JavaConfigApplicationContext} or via XML using {@link ConfigurationPostProcessor}. In
* any case, tooling (Spring IDE) will use {@link AsmJavaConfigBeanDefinitionReader}directly,
* any case, tooling (Spring IDE) will use {@link ConfigurationClassBeanDefinitionReader}directly,
* thus never encountering this classloading. Should this become problematic, it would not be
* too difficult to replace the following with ASM logic that traverses the class hierarchy in
* order to find whether the class is directly or indirectly annotated with
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册