+ Eliminated UsageError/Validatable/MalformedConfigurationException in favor of existing Problem/ProblemReporter types
+ Pruned a number of attributes from the @Bean and @Configuration annotations
This commit is contained in:
parent
c41c64389f
commit
100ba6599f
|
|
@ -22,10 +22,6 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
|
||||
|
||||
/**
|
||||
* Annotation to be applied to methods that create beans in a Spring context. The name of
|
||||
|
|
@ -65,33 +61,39 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
|||
@Documented
|
||||
public @interface Bean {
|
||||
|
||||
/**
|
||||
* Role this bean plays in the overall application configuration.
|
||||
*
|
||||
* @see BeanDefinition#ROLE_APPLICATION
|
||||
* @see BeanDefinition#ROLE_INFRASTRUCTURE
|
||||
* @see BeanDefinition#ROLE_SUPPORT
|
||||
*
|
||||
* @see AbstractBeanDefinition the 'role' field is assigned by default to
|
||||
* ROLE_APPLICATION
|
||||
*/
|
||||
int role() default BeanDefinition.ROLE_APPLICATION;
|
||||
// TODO:
|
||||
// /**
|
||||
// * Role this bean plays in the overall application configuration.
|
||||
// *
|
||||
// * @see BeanDefinition#ROLE_APPLICATION
|
||||
// * @see BeanDefinition#ROLE_INFRASTRUCTURE
|
||||
// * @see BeanDefinition#ROLE_SUPPORT
|
||||
// *
|
||||
// * @see AbstractBeanDefinition the 'role' field is assigned by default to
|
||||
// * ROLE_APPLICATION
|
||||
// */
|
||||
// int role() default BeanDefinition.ROLE_APPLICATION;
|
||||
|
||||
/**
|
||||
* Bean aliases.
|
||||
*/
|
||||
String[] aliases() default {};
|
||||
String[] name() default {};
|
||||
|
||||
/**
|
||||
* Scope: whether the bean is a singleton, prototype or custom scope. Default is
|
||||
* singleton.
|
||||
*/
|
||||
String scope() default StandardScopes.SINGLETON;
|
||||
// TODO: Prune aliases, favor name[]
|
||||
// /**
|
||||
// * Bean aliases.
|
||||
// */
|
||||
// String[] aliases() default {};
|
||||
|
||||
/**
|
||||
* Bean autowire strategy.
|
||||
*/
|
||||
Autowire autowire() default Autowire.INHERITED;
|
||||
// TODO: favor @Scope
|
||||
// /**
|
||||
// * Scope: whether the bean is a singleton, prototype or custom scope. Default is
|
||||
// * singleton.
|
||||
// */
|
||||
// String scope() default StandardScopes.SINGLETON;
|
||||
|
||||
// TODO: prune autowiring?
|
||||
// /**
|
||||
// * Bean autowire strategy.
|
||||
// */
|
||||
// Autowire autowire() default Autowire.INHERITED;
|
||||
|
||||
// /**
|
||||
// * Bean lazy strategy.
|
||||
|
|
@ -111,13 +113,14 @@ public @interface Bean {
|
|||
* Bean init method name. Normally this is not needed, as the initialization (with
|
||||
* parameterization) can be done directly through java code.
|
||||
*/
|
||||
String initMethodName() default "";
|
||||
String initMethod() default "";
|
||||
|
||||
/**
|
||||
* Bean destroy method name.
|
||||
*/
|
||||
String destroyMethodName() default "";
|
||||
String destroyMethod() default "";
|
||||
|
||||
// TODO: Prune DependencyCheck
|
||||
// /**
|
||||
// * Bean dependency check strategy.
|
||||
// */
|
||||
|
|
@ -128,19 +131,23 @@ public @interface Bean {
|
|||
*/
|
||||
String[] dependsOn() default {};
|
||||
|
||||
// TODO: Prune @Meta
|
||||
// /**
|
||||
// * Metadata for the current bean.
|
||||
// */
|
||||
// Meta[] meta() default { };
|
||||
|
||||
/**
|
||||
* Allow the bean to be overridden in another JavaConfig, XML or other non-Java
|
||||
* configuration. This is consistent with DefaultListableBeanFactory's
|
||||
* allowBeanDefinitionOverriding property, which defaults to true.
|
||||
*
|
||||
* @return whether overriding of this bean is allowed
|
||||
*/
|
||||
boolean allowOverriding() default true;
|
||||
// TODO: Prune allowOverriding
|
||||
// /**
|
||||
// * Allow the bean to be overridden in another JavaConfig, XML or other non-Java
|
||||
// * configuration. This is consistent with DefaultListableBeanFactory's
|
||||
// * allowBeanDefinitionOverriding property, which defaults to true.
|
||||
// *
|
||||
// * @return whether overriding of this bean is allowed
|
||||
// */
|
||||
// boolean allowOverriding() default true;
|
||||
//
|
||||
//String name() default "";
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,16 +16,22 @@
|
|||
package org.springframework.config.java;
|
||||
|
||||
import static java.lang.String.*;
|
||||
import static org.springframework.config.java.StandardScopes.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.parsing.Location;
|
||||
import org.springframework.beans.factory.parsing.Problem;
|
||||
import org.springframework.beans.factory.parsing.ProblemReporter;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
public final class BeanMethod implements Validatable {
|
||||
public final class BeanMethod {
|
||||
|
||||
private final String name;
|
||||
private final int modifiers;
|
||||
|
|
@ -65,9 +71,8 @@ public final class BeanMethod implements Validatable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the annotation on this method matching <var>annoType</var> or null
|
||||
* IllegalStateException} if not present.
|
||||
*
|
||||
* @return the annotation on this method matching <var>annoType</var> or
|
||||
* {@literal null} if not present.
|
||||
* @see #getRequiredAnnotation(Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
@ -80,9 +85,8 @@ public final class BeanMethod implements Validatable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the annotation on this method matching <var>annoType</var> or throws
|
||||
* {@link IllegalStateException} if not present.
|
||||
*
|
||||
* @return the annotation on this method matching <var>annoType</var>
|
||||
* @throws {@link IllegalStateException} if not present
|
||||
* @see #getAnnotation(Class)
|
||||
*/
|
||||
public <T extends Annotation> T getRequiredAnnotation(Class<T> annoType) {
|
||||
|
|
@ -96,7 +100,7 @@ public final class BeanMethod implements Validatable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets up bi-directional relationship between this method and its declaring class.
|
||||
* Set up a bi-directional relationship between this method and its declaring class.
|
||||
*
|
||||
* @see ConfigurationClass#addMethod(BeanMethod)
|
||||
*/
|
||||
|
|
@ -116,22 +120,20 @@ public final class BeanMethod implements Validatable {
|
|||
return lineNumber;
|
||||
}
|
||||
|
||||
public void validate(List<UsageError> errors) {
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
|
||||
if (Modifier.isPrivate(getModifiers()))
|
||||
errors.add(new PrivateMethodError());
|
||||
problemReporter.error(new PrivateMethodError());
|
||||
|
||||
if (Modifier.isFinal(getModifiers()))
|
||||
errors.add(new FinalMethodError());
|
||||
problemReporter.error(new FinalMethodError());
|
||||
|
||||
if (this.getAnnotation(ScopedProxy.class) == null)
|
||||
return;
|
||||
|
||||
Bean bean =this.getRequiredAnnotation(Bean.class);
|
||||
|
||||
if (bean.scope().equals(StandardScopes.SINGLETON)
|
||||
|| bean.scope().equals(StandardScopes.PROTOTYPE))
|
||||
errors.add(new InvalidScopedProxyDeclarationError(this));
|
||||
Scope scope = this.getAnnotation(Scope.class);
|
||||
if(scope == null || scope.equals(SINGLETON) || scope.equals(PROTOTYPE))
|
||||
problemReporter.error(new InvalidScopedProxyDeclarationError(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -181,27 +183,17 @@ public final class BeanMethod implements Validatable {
|
|||
return true;
|
||||
}
|
||||
|
||||
/** JavaConfigMethods must be visible (non-private) in order to accommodate CGLIB. */
|
||||
public class PrivateMethodError extends UsageError {
|
||||
/** {@link Bean} methods must be non-private in order to accommodate CGLIB. */
|
||||
public class PrivateMethodError extends Problem {
|
||||
public PrivateMethodError() {
|
||||
super(getDeclaringClass(), getLineNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return format("method '%s' may not be private", getName());
|
||||
super(format("method '%s' may not be private", getName()), new Location(new FileSystemResource("/dev/null")));
|
||||
}
|
||||
}
|
||||
|
||||
/** JavaConfigMethods must be extensible (non-final) in order to accommodate CGLIB. */
|
||||
public class FinalMethodError extends UsageError {
|
||||
/** {@link Bean} methods must be non-final in order to accommodate CGLIB. */
|
||||
public class FinalMethodError extends Problem {
|
||||
public FinalMethodError() {
|
||||
super(getDeclaringClass(), getLineNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return format("method '%s' may not be final - remove the final modifier to continue", getName());
|
||||
super(format("method '%s' may not be final. remove the final modifier to continue", getName()), new Location(new FileSystemResource("/dev/null")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import static java.lang.String.*;
|
|||
import static org.springframework.util.StringUtils.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
|
@ -15,6 +17,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
|||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
|
||||
|
|
@ -43,19 +46,27 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
|
|||
|
||||
Bean bean = method.getRequiredAnnotation(Bean.class);
|
||||
|
||||
Configuration defaults = configClass.getMetadata();
|
||||
// TODO: prune defaults
|
||||
//Configuration defaults = configClass.getMetadata();
|
||||
|
||||
// consider scoping
|
||||
beanDef.setScope(bean.scope());
|
||||
Scope scope = method.getAnnotation(Scope.class);
|
||||
if(scope != null)
|
||||
beanDef.setScope(scope.value());
|
||||
|
||||
// consider autowiring
|
||||
if (bean.autowire() != AnnotationUtils.getDefaultValue(Bean.class, "autowire"))
|
||||
beanDef.setAutowireMode(bean.autowire().value());
|
||||
else if (defaults.defaultAutowire() != AnnotationUtils.getDefaultValue(Configuration.class,
|
||||
"defaultAutowire"))
|
||||
beanDef.setAutowireMode(defaults.defaultAutowire().value());
|
||||
// TODO: prune autowiring
|
||||
// // consider autowiring
|
||||
// if (bean.autowire() != AnnotationUtils.getDefaultValue(Bean.class, "autowire"))
|
||||
// beanDef.setAutowireMode(bean.autowire().value());
|
||||
// else if (defaults.defaultAutowire() != AnnotationUtils.getDefaultValue(Configuration.class,
|
||||
// "defaultAutowire"))
|
||||
// beanDef.setAutowireMode(defaults.defaultAutowire().value());
|
||||
|
||||
String beanName = method.getName();
|
||||
// consider name and any aliases
|
||||
ArrayList<String> names = new ArrayList<String>(Arrays.asList(bean.name()));
|
||||
String beanName = (names.size() > 0) ? names.remove(0) : method.getName();
|
||||
for (String alias : bean.name())
|
||||
registry.registerAlias(beanName, alias);
|
||||
|
||||
// has this already been overriden (i.e.: via XML)?
|
||||
if (containsBeanDefinitionIncludingAncestry(beanName, registry)) {
|
||||
|
|
@ -65,11 +76,12 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
|
|||
if (!(existingBeanDef instanceof ConfigurationClassBeanDefinition)) {
|
||||
// no -> then it's an external override, probably XML
|
||||
|
||||
// ensure that overriding is ok
|
||||
if (bean.allowOverriding() == false) {
|
||||
UsageError error = configClass.new IllegalBeanOverrideError(null, method);
|
||||
throw new MalformedConfigurationException(error);
|
||||
}
|
||||
// TODO: Prune this
|
||||
// // ensure that overriding is ok
|
||||
// if (bean.allowOverriding() == false) {
|
||||
// UsageError error = configClass.new IllegalBeanOverrideError(null, method);
|
||||
// throw new MalformedConfigurationException(error);
|
||||
// }
|
||||
|
||||
// overriding is legal, return immediately
|
||||
logger.info(format("Skipping loading bean definition for %s: a definition for bean "
|
||||
|
|
@ -78,13 +90,6 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
|
|||
}
|
||||
}
|
||||
|
||||
// propagate this bean's 'role' attribute
|
||||
beanDef.setRole(bean.role());
|
||||
|
||||
// consider aliases
|
||||
for (String alias : bean.aliases())
|
||||
registry.registerAlias(beanName, alias);
|
||||
|
||||
// TODO: re-enable for Lazy support
|
||||
// // is this bean marked as primary for disambiguation?
|
||||
// if (bean.primary() == Primary.TRUE)
|
||||
|
|
@ -96,12 +101,12 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
|
|||
// beanDef.setLazyInit(true);
|
||||
|
||||
// does this bean have a custom init-method specified?
|
||||
String initMethodName = bean.initMethodName();
|
||||
String initMethodName = bean.initMethod();
|
||||
if (hasText(initMethodName))
|
||||
beanDef.setInitMethodName(initMethodName);
|
||||
|
||||
// does this bean have a custom destroy-method specified?
|
||||
String destroyMethodName = bean.destroyMethodName();
|
||||
String destroyMethodName = bean.destroyMethod();
|
||||
if (hasText(destroyMethodName))
|
||||
beanDef.setDestroyMethodName(destroyMethodName);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
|
|
@ -44,9 +42,13 @@ import org.springframework.stereotype.Component;
|
|||
* fact that this annotation is meta-annotated with {@link Component @Component}.
|
||||
* </p>
|
||||
*
|
||||
* May be used in conjunction with {@link Lazy}
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @since 3.0
|
||||
* @see Lazy
|
||||
* @see Bean
|
||||
*/
|
||||
@Component
|
||||
@Target( { ElementType.TYPE })
|
||||
|
|
@ -55,22 +57,25 @@ import org.springframework.stereotype.Component;
|
|||
@Documented
|
||||
public @interface Configuration {
|
||||
|
||||
/**
|
||||
* Configuration name. Allow different variants, such as test, production etc. Default
|
||||
* will always match.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String[] names() default "";
|
||||
// TODO: consider pruning @Configuration(name[])
|
||||
// /**
|
||||
// * Configuration name. Allow different variants, such as test, production etc. Default
|
||||
// * will always match.
|
||||
// *
|
||||
// * @return
|
||||
// */
|
||||
// String[] name() default "";
|
||||
|
||||
/**
|
||||
* Specifies the default autowiring strategy.
|
||||
*
|
||||
* @see Autowire
|
||||
* @return
|
||||
*/
|
||||
Autowire defaultAutowire() default Autowire.INHERITED;
|
||||
// TODO: Prune defaultAutowire
|
||||
// /**
|
||||
// * Specifies the default autowiring strategy.
|
||||
// *
|
||||
// * @see Autowire
|
||||
// * @return
|
||||
// */
|
||||
// Autowire defaultAutowire() default Autowire.INHERITED;
|
||||
|
||||
// TODO: Prune DependencyCheck
|
||||
// /**
|
||||
// * Dependency check strategy. By default, the dependency check is
|
||||
// * unspecified, that is the default Spring option will apply. In most cases,
|
||||
|
|
@ -81,6 +86,8 @@ public @interface Configuration {
|
|||
// */
|
||||
// DependencyCheck defaultDependencyCheck() default DependencyCheck.UNSPECIFIED;
|
||||
//
|
||||
|
||||
// TODO: Favor @Lazy at the @Configuration class level. Should have @Target(TYPE, METHOD)
|
||||
// /**
|
||||
// * Bean instantiation strategy. By default, it is unspecified.
|
||||
// *
|
||||
|
|
@ -89,14 +96,16 @@ public @interface Configuration {
|
|||
// */
|
||||
// Lazy defaultLazy() default Lazy.UNSPECIFIED;
|
||||
|
||||
/**
|
||||
* Do we autowire with aspects from the enclosing factory scope?
|
||||
*/
|
||||
boolean useFactoryAspects() default false;
|
||||
// TODO: prune useFactoryAspects
|
||||
// /**
|
||||
// * Do we autowire with aspects from the enclosing factory scope?
|
||||
// */
|
||||
// boolean useFactoryAspects() default false;
|
||||
|
||||
/**
|
||||
* Do we check {@link Required @Required} methods to make sure they've been called?
|
||||
*/
|
||||
boolean checkRequired() default false;
|
||||
// TODO: this is the default, and needs to be switched off at annotation-config
|
||||
// /**
|
||||
// * Do we check {@link Required @Required} methods to make sure they've been called?
|
||||
// */
|
||||
// boolean checkRequired() default false;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,12 @@ import static java.lang.String.*;
|
|||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.parsing.Location;
|
||||
import org.springframework.beans.factory.parsing.Problem;
|
||||
import org.springframework.beans.factory.parsing.ProblemReporter;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import sun.security.x509.Extension;
|
||||
|
|
@ -47,7 +50,7 @@ import sun.security.x509.Extension;
|
|||
*/
|
||||
// TODO: SJC-242 update documentation in light of generalization changes
|
||||
// consider removing all refs to Bean, ExternalBean, etc.
|
||||
public final class ConfigurationClass extends ModelClass implements Validatable {
|
||||
public final class ConfigurationClass extends ModelClass {
|
||||
|
||||
private String beanName;
|
||||
|
||||
|
|
@ -174,18 +177,18 @@ public final class ConfigurationClass extends ModelClass implements Validatable
|
|||
return this;
|
||||
}
|
||||
|
||||
public void validate(List<UsageError> errors) {
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
|
||||
// configuration classes must be annotated with @Configuration
|
||||
if (metadata == null)
|
||||
errors.add(new NonAnnotatedConfigurationError());
|
||||
problemReporter.error(new NonAnnotatedConfigurationError());
|
||||
|
||||
// a configuration class may not be final (CGLIB limitation)
|
||||
if (Modifier.isFinal(modifiers))
|
||||
errors.add(new FinalConfigurationError());
|
||||
problemReporter.error(new FinalConfigurationError());
|
||||
|
||||
for (BeanMethod method : methods)
|
||||
method.validate(errors);
|
||||
method.validate(problemReporter);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -248,94 +251,27 @@ public final class ConfigurationClass extends ModelClass implements Validatable
|
|||
|
||||
|
||||
/** Configuration classes must be annotated with {@link Configuration @Configuration}. */
|
||||
public class NonAnnotatedConfigurationError extends UsageError {
|
||||
public class NonAnnotatedConfigurationError extends Problem {
|
||||
public NonAnnotatedConfigurationError() {
|
||||
super(ConfigurationClass.this, -1);
|
||||
super(
|
||||
format("%s was provided as a Java Configuration class but was not annotated with @%s. "
|
||||
+ "Update the class definition to continue.", getSimpleName(), Configuration.class
|
||||
.getSimpleName()),
|
||||
new Location(new FileSystemResource("/dev/null"))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return format("%s was provided as a Java Configuration class but was not annotated with @%s. "
|
||||
+ "Update the class definition to continue.", getSimpleName(), Configuration.class
|
||||
.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
/** Configuration classes must be non-final to accommodate CGLIB subclassing. */
|
||||
public class FinalConfigurationError extends UsageError {
|
||||
public class FinalConfigurationError extends Problem {
|
||||
public FinalConfigurationError() {
|
||||
super(ConfigurationClass.this, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return format("@%s class may not be final. Remove the final modifier to continue.",
|
||||
Configuration.class.getSimpleName());
|
||||
super(
|
||||
format("@%s class may not be final. Remove the final modifier to continue.",
|
||||
Configuration.class.getSimpleName()),
|
||||
new Location(new FileSystemResource("/dev/null"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class InvalidPluginException extends UsageError {
|
||||
|
||||
private final Annotation invalidPluginAnnotation;
|
||||
|
||||
public InvalidPluginException(Annotation invalidPluginAnnotation) {
|
||||
super(ConfigurationClass.this, -1);
|
||||
this.invalidPluginAnnotation = invalidPluginAnnotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return format("Annotation [%s] was not annotated with @Plugin", invalidPluginAnnotation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Error raised when a Bean marked as 'allowOverriding=false' is attempted to be
|
||||
* overridden by another bean definition.
|
||||
*
|
||||
* @see Bean#allowOverriding()
|
||||
*/
|
||||
public class IllegalBeanOverrideError extends UsageError {
|
||||
private final ConfigurationClass authoritativeClass;
|
||||
private final BeanMethod finalMethodInQuestion;
|
||||
|
||||
/**
|
||||
* Creates a new IllegalBeanOverrideError object.
|
||||
*
|
||||
* @param violatingClass class attempting an illegal override. null value signifies
|
||||
* that the violating class is unknown or that there is no class to speak of
|
||||
* (in the case of an XML bean definition doing the illegal overriding)
|
||||
* @param finalMethodInQuestion the method that has been marked
|
||||
* 'allowOverriding=false'
|
||||
*/
|
||||
public IllegalBeanOverrideError(ConfigurationClass violatingClass, BeanMethod finalMethodInQuestion) {
|
||||
super(violatingClass, -1);
|
||||
this.authoritativeClass = ConfigurationClass.this;
|
||||
this.finalMethodInQuestion = finalMethodInQuestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return format("Illegal attempt by '%s' to override bean definition originally "
|
||||
+ "specified by %s.%s. Consider removing 'allowOverride=false' from original method.",
|
||||
finalMethodInQuestion.getName(), authoritativeClass.getSimpleName(),
|
||||
finalMethodInQuestion.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasMethod(String methodName) {
|
||||
return getMethod(methodName) != null;
|
||||
}
|
||||
|
||||
public BeanMethod getMethod(String methodName) {
|
||||
|
||||
for (BeanMethod method : methods)
|
||||
if (methodName.equals(method.getName()))
|
||||
return method;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,11 @@ package org.springframework.config.java;
|
|||
import static java.lang.String.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.parsing.Location;
|
||||
import org.springframework.beans.factory.parsing.Problem;
|
||||
import org.springframework.beans.factory.parsing.ProblemReporter;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
||||
|
||||
|
||||
|
|
@ -39,7 +43,7 @@ import java.util.List;
|
|||
* @author Chris Beams
|
||||
* @see org.springframework.config.java.internal.parsing.ConfigurationParser
|
||||
*/
|
||||
public final class ConfigurationModel implements Validatable {
|
||||
public final class ConfigurationModel {
|
||||
|
||||
/* list is used because order and collection equality matters. */
|
||||
private final ArrayList<ConfigurationClass> configurationClasses = new ArrayList<ConfigurationClass>();
|
||||
|
|
@ -89,35 +93,40 @@ public final class ConfigurationModel implements Validatable {
|
|||
* Recurses through the model validating each object along the way and aggregating any
|
||||
* <var>errors</var>.
|
||||
*
|
||||
* @see ConfigurationClass#validate(java.util.List)
|
||||
* @see BeanMethod#validate(java.util.List)
|
||||
* @see UsageError
|
||||
* @see ConfigurationClass#validate
|
||||
* @see BeanMethod#validate
|
||||
*/
|
||||
public void validate(List<UsageError> errors) {
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
// user must specify at least one configuration
|
||||
if (configurationClasses.isEmpty())
|
||||
errors.add(new EmptyModelError());
|
||||
problemReporter.error(new EmptyModelError());
|
||||
|
||||
// check for any illegal @Bean overriding
|
||||
ConfigurationClass[] allClasses = getAllConfigurationClasses();
|
||||
for (int i = 0; i < allClasses.length; i++) {
|
||||
for (BeanMethod method : allClasses[i].getMethods()) {
|
||||
Bean bean = method.getAnnotation(Bean.class);
|
||||
|
||||
if (bean == null || bean.allowOverriding())
|
||||
continue;
|
||||
|
||||
for (int j = i + 1; j < allClasses.length; j++)
|
||||
if (allClasses[j].hasMethod(method.getName()))
|
||||
errors.add(allClasses[i].new IllegalBeanOverrideError(allClasses[j], method));
|
||||
}
|
||||
}
|
||||
// TODO: prune this
|
||||
// // check for any illegal @Bean overriding
|
||||
// ConfigurationClass[] allClasses = getAllConfigurationClasses();
|
||||
// for (int i = 0; i < allClasses.length; i++) {
|
||||
// for (BeanMethod method : allClasses[i].getMethods()) {
|
||||
// Bean bean = method.getAnnotation(Bean.class);
|
||||
//
|
||||
// if (bean == null || bean.allowOverriding())
|
||||
// continue;
|
||||
//
|
||||
// for (int j = i + 1; j < allClasses.length; j++)
|
||||
// if (allClasses[j].hasMethod(method.getName()))
|
||||
// problemReporter.error(
|
||||
// new Problem(
|
||||
// allClasses[i].new IllegalBeanOverrideError(allClasses[j], method).getDescription(),
|
||||
// new Location(new ClassPathResource(allClasses[i].getName().replace('.', '/').concat(".class")))
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// each individual configuration class must be well-formed
|
||||
// note that each configClass detects usage errors on its imports recursively
|
||||
// note that each configClass will recursively process its respective methods
|
||||
for (ConfigurationClass configClass : configurationClasses)
|
||||
configClass.validate(errors);
|
||||
configClass.validate(problemReporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -151,15 +160,13 @@ public final class ConfigurationModel implements Validatable {
|
|||
}
|
||||
|
||||
|
||||
public class EmptyModelError extends UsageError {
|
||||
public class EmptyModelError extends Problem {
|
||||
public EmptyModelError() {
|
||||
super(null, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return format("Configuration model was empty. Make sure at least one "
|
||||
+ "@%s class has been specified.", Configuration.class.getSimpleName());
|
||||
super(
|
||||
format("Configuration model was empty. Make sure at least one "
|
||||
+ "@%s class has been specified.", Configuration.class.getSimpleName()),
|
||||
new Location(new FileSystemResource("/dev/null"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@
|
|||
*/
|
||||
package org.springframework.config.java;
|
||||
|
||||
import org.springframework.beans.factory.parsing.Location;
|
||||
import org.springframework.beans.factory.parsing.Problem;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
||||
public class InvalidScopedProxyDeclarationError extends UsageError {
|
||||
private final BeanMethod method;
|
||||
|
||||
public class InvalidScopedProxyDeclarationError extends Problem {
|
||||
public InvalidScopedProxyDeclarationError(BeanMethod method) {
|
||||
super(method.getDeclaringClass(), method.getLineNumber());
|
||||
this.method = method;
|
||||
super(
|
||||
String.format("method %s contains an invalid annotation declaration: @%s "
|
||||
+ "cannot be used on a singleton/prototype bean", method.getName(), ScopedProxy.class
|
||||
.getSimpleName()),
|
||||
new Location(new FileSystemResource("/dev/null"))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return String.format("method %s contains an invalid annotation declaration: @%s "
|
||||
+ "cannot be used on a singleton/prototype bean", method.getName(), ScopedProxy.class
|
||||
.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* TODO: rename to UsageException / move outside .internal?
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MalformedConfigurationException extends RuntimeException {
|
||||
|
||||
private final List<? extends UsageError> errors;
|
||||
|
||||
public MalformedConfigurationException(String message) {
|
||||
super(message);
|
||||
this.errors = new ArrayList<UsageError>();
|
||||
}
|
||||
|
||||
public MalformedConfigurationException(UsageError... errors) {
|
||||
super(toString(errors));
|
||||
this.errors = Arrays.asList(errors);
|
||||
}
|
||||
|
||||
public boolean containsError(Class<? extends UsageError> errorType) {
|
||||
for (UsageError error : errors)
|
||||
if (error.getClass().isAssignableFrom(errorType))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a list of syntax errors as output suitable for diagnosis via System.err.
|
||||
*/
|
||||
private static String toString(UsageError... errors) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("\n");
|
||||
|
||||
if (errors.length == 1)
|
||||
sb.append("A usage error has ");
|
||||
else
|
||||
sb.append(errors.length + " usage errors have ");
|
||||
|
||||
sb.append("been detected:\n");
|
||||
|
||||
for (int i = 0; i < errors.length; i++) {
|
||||
sb.append(errors[i].toString());
|
||||
if ((i + 1) < errors.length)
|
||||
sb.append('\n');
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
/**
|
||||
* Represents an invalid usage of JavaConfig constructs, e.g. a {@link Configuration} that
|
||||
* declares no {@link Bean @Bean} methods, or declaring both {@link Bean @Bean} and
|
||||
* {@link ExternalBean @ExternalBean} on a single method. Explore the type hierarchy to
|
||||
* discover all possible usage errors.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @see MalformedConfigurationException
|
||||
*/
|
||||
public abstract class UsageError {
|
||||
|
||||
private final ModelClass clazz;
|
||||
private final int lineNumber;
|
||||
|
||||
/**
|
||||
* Create a new usage error, providing information about where the error was detected.
|
||||
*
|
||||
* @param modelClass class in which this error was detected. Null value indicates that
|
||||
* the error was not local to a single class.
|
||||
* @param lineNumber line number on which this error was detected (useful for tooling
|
||||
* integration)
|
||||
*
|
||||
* @see ModelClass#getSource()
|
||||
*/
|
||||
public UsageError(ModelClass modelClass, int lineNumber) {
|
||||
this.clazz = modelClass;
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable description of this error suitable for console output or IDE tooling.
|
||||
*/
|
||||
public abstract String getDescription();
|
||||
|
||||
/**
|
||||
* Same as {@link #getDescription()} but attributed with class and line number
|
||||
* information. If modelClass constructor parameter was null, class and line number
|
||||
* information will be omitted.
|
||||
*/
|
||||
public final String getAttributedDescription() {
|
||||
if (clazz == null)
|
||||
return getDescription();
|
||||
|
||||
return String.format("%s:%d: %s", clazz.getSource(), lineNumber, getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates directly to {@link #getAttributedDescription()}.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAttributedDescription();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package org.springframework.config.java;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a type is able to be validated for errors.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
interface Validatable {
|
||||
|
||||
/**
|
||||
* Validates this object, adding any errors to the supplied list of <var>errors</var>.
|
||||
*/
|
||||
public void validate(List<UsageError> errors);
|
||||
|
||||
}
|
||||
|
|
@ -174,6 +174,7 @@ public class ConfigurationEnhancer {
|
|||
* @return original subclass instance unless superclass is annnotated with @Aspect, in
|
||||
* which case a subclass of the subclass is returned
|
||||
*/
|
||||
// TODO: try to implement with modifications to AbstractAspectJAdvisorFactory#isAspect
|
||||
private Class<?> nestOneClassDeeperIfAspect(Class<?> superclass, Class<?> origSubclass) {
|
||||
boolean superclassIsAnAspect = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
package org.springframework.config.java.support;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
|
||||
import org.springframework.beans.factory.parsing.ProblemReporter;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.config.java.Bean;
|
||||
import org.springframework.config.java.Configuration;
|
||||
import org.springframework.config.java.ConfigurationModel;
|
||||
import org.springframework.config.java.MalformedConfigurationException;
|
||||
import org.springframework.config.java.internal.parsing.ConfigurationParser;
|
||||
|
||||
|
||||
|
|
@ -44,6 +46,14 @@ import org.springframework.config.java.internal.parsing.ConfigurationParser;
|
|||
*/
|
||||
public abstract class AbstractConfigurationClassProcessor {
|
||||
|
||||
/**
|
||||
* Used to register any problems detected with {@link Configuration} or {@link Bean}
|
||||
* declarations. For instance, a Bean method marked as {@literal final} is illegal
|
||||
* and would be reported as a problem. Defaults to {@link FailFastProblemReporter},
|
||||
* but is overridable with {@link #setProblemReporter}
|
||||
*/
|
||||
private ProblemReporter problemReporter = new FailFastProblemReporter();
|
||||
|
||||
/**
|
||||
* Populate and return a registry containing all {@link Configuration} bean definitions
|
||||
* to be processed.
|
||||
|
|
@ -65,12 +75,27 @@ public abstract class AbstractConfigurationClassProcessor {
|
|||
|
||||
/**
|
||||
* Validate the given model and handle any errors. Implementations may choose to throw
|
||||
* {@link MalformedConfigurationException}, or in the case of tooling register problems
|
||||
* {@link BeanDefinitionParsingException}, or in the case of tooling register problems
|
||||
* with the UI.
|
||||
* @param configModel {@link ConfigurationModel} to validate
|
||||
*/
|
||||
protected abstract void validateModel(ConfigurationModel configModel);
|
||||
|
||||
/**
|
||||
* Override the default {@link ProblemReporter}.
|
||||
* @param problemReporter custom problem reporter
|
||||
*/
|
||||
protected final void setProblemReporter(ProblemReporter problemReporter) {
|
||||
this.problemReporter = problemReporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently registered {@link ProblemReporter}.
|
||||
*/
|
||||
protected final ProblemReporter getProblemReporter() {
|
||||
return problemReporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and validate a {@link ConfigurationModel} based on the registry of
|
||||
* {@link Configuration} classes provided by {@link #getConfigurationBeanDefinitions},
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package org.springframework.config.java.support;
|
|||
import static java.lang.String.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
|
@ -31,8 +30,6 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
|||
import org.springframework.config.java.Bean;
|
||||
import org.springframework.config.java.Configuration;
|
||||
import org.springframework.config.java.ConfigurationModel;
|
||||
import org.springframework.config.java.MalformedConfigurationException;
|
||||
import org.springframework.config.java.UsageError;
|
||||
import org.springframework.config.java.internal.enhancement.ConfigurationEnhancer;
|
||||
import org.springframework.config.java.internal.parsing.ConfigurationParser;
|
||||
import org.springframework.core.Ordered;
|
||||
|
|
@ -136,15 +133,12 @@ public class ConfigurationClassPostProcessor extends AbstractConfigurationClassP
|
|||
}
|
||||
|
||||
/**
|
||||
* Validates the given <var>model</var>.
|
||||
* @throws MalformedConfigurationException if any errors are detected
|
||||
* Validates the given <var>model</var>. Any problems found are delegated
|
||||
* to {@link #getProblemReporter()}.
|
||||
*/
|
||||
@Override
|
||||
protected void validateModel(ConfigurationModel model) {
|
||||
ArrayList<UsageError> errors = new ArrayList<UsageError>();
|
||||
model.validate(errors);
|
||||
if (errors.size() > 0)
|
||||
throw new MalformedConfigurationException(errors.toArray(new UsageError[] {}));
|
||||
model.validate(this.getProblemReporter());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -19,12 +19,10 @@ import static java.lang.String.*;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
|
||||
import org.springframework.config.java.Bean;
|
||||
import org.springframework.config.java.BeanMethod;
|
||||
|
|
@ -96,18 +94,18 @@ class ConfigurationModelBeanDefinitionReader {
|
|||
* @param beanDefs
|
||||
*/
|
||||
private void doLoadBeanDefinitionForConfigurationClass(ConfigurationClass configClass) {
|
||||
Configuration metadata = configClass.getMetadata();
|
||||
|
||||
// TODO: think about implications with annotation-config
|
||||
if (metadata.checkRequired() == true) {
|
||||
RootBeanDefinition requiredAnnotationPostProcessor = new RootBeanDefinition();
|
||||
Class<?> beanClass = RequiredAnnotationBeanPostProcessor.class;
|
||||
String beanName = beanClass.getName() + "#0";
|
||||
requiredAnnotationPostProcessor.setBeanClass(beanClass);
|
||||
requiredAnnotationPostProcessor
|
||||
.setResourceDescription("ensures @Required methods have been invoked");
|
||||
registry.registerBeanDefinition(beanName, requiredAnnotationPostProcessor);
|
||||
}
|
||||
// TODO: prune support for @Required
|
||||
// Configuration metadata = configClass.getMetadata();
|
||||
// if (metadata.checkRequired() == true) {
|
||||
// RootBeanDefinition requiredAnnotationPostProcessor = new RootBeanDefinition();
|
||||
// Class<?> beanClass = RequiredAnnotationBeanPostProcessor.class;
|
||||
// String beanName = beanClass.getName() + "#0";
|
||||
// requiredAnnotationPostProcessor.setBeanClass(beanClass);
|
||||
// requiredAnnotationPostProcessor
|
||||
// .setResourceDescription("ensures @Required methods have been invoked");
|
||||
// registry.registerBeanDefinition(beanName, requiredAnnotationPostProcessor);
|
||||
// }
|
||||
|
||||
GenericBeanDefinition configBeanDef = new GenericBeanDefinition();
|
||||
configBeanDef.setBeanClassName(configClass.getName());
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
|||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.config.java.Bean;
|
||||
import org.springframework.config.java.Configuration;
|
||||
import org.springframework.config.java.MalformedConfigurationException;
|
||||
import org.springframework.config.java.StandardScopes;
|
||||
import org.springframework.config.java.support.ConfigurationClassPostProcessor;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
|
@ -96,68 +96,10 @@ public class BasicTests {
|
|||
return bar;
|
||||
}
|
||||
|
||||
@Bean(scope = StandardScopes.PROTOTYPE)
|
||||
@Bean @Scope(StandardScopes.PROTOTYPE)
|
||||
public TestBean baz() {
|
||||
return new TestBean("bar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void legalBeanOverriding() {
|
||||
{
|
||||
BeanFactory factory = initBeanFactory(ConfigWithBeanThatAllowsOverriding.class, ConfigWithBeanOverride.class);
|
||||
|
||||
TestBean testBean = factory.getBean("testBean", TestBean.class);
|
||||
|
||||
assertThat(testBean.getName(), equalTo("overridden"));
|
||||
}
|
||||
|
||||
// now try it the other way around - order matters!
|
||||
|
||||
{
|
||||
BeanFactory factory = initBeanFactory(ConfigWithBeanOverride.class, ConfigWithBeanThatAllowsOverriding.class);
|
||||
|
||||
TestBean testBean = factory.getBean("testBean", TestBean.class);
|
||||
|
||||
assertThat(testBean.getName(), equalTo("original"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test(expected=MalformedConfigurationException.class)
|
||||
public void illegalBeanOverriding() {
|
||||
initBeanFactory(ConfigWithBeanThatDisallowsOverriding.class, ConfigWithBeanOverride.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void illegalBeanOverriding2() {
|
||||
// should be okay when the class that disallows overriding is the one doing the overriding
|
||||
initBeanFactory(ConfigWithBeanOverride.class, ConfigWithBeanThatDisallowsOverriding.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithBeanThatAllowsOverriding {
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean("original");
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithBeanThatDisallowsOverriding {
|
||||
@Bean(allowOverriding = false)
|
||||
public TestBean testBean() {
|
||||
return new TestBean("original");
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithBeanOverride {
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean("overridden");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,10 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.springframework.aop.scope.ScopedObject;
|
||||
import org.springframework.beans.factory.config.Scope;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.config.java.Bean;
|
||||
import org.springframework.config.java.Configuration;
|
||||
import org.springframework.config.java.InvalidScopedProxyDeclarationError;
|
||||
import org.springframework.config.java.MalformedConfigurationException;
|
||||
import org.springframework.config.java.ScopedProxy;
|
||||
import org.springframework.config.java.StandardScopes;
|
||||
import org.springframework.config.java.support.ConfigurationClassPostProcessor;
|
||||
|
|
@ -118,8 +117,8 @@ public class ScopingTests {
|
|||
try {
|
||||
createContext(null, InvalidProxyOnPredefinedScopesConfiguration.class);
|
||||
fail("exception expected");
|
||||
} catch (MalformedConfigurationException ex) {
|
||||
assertTrue(ex.containsError(InvalidScopedProxyDeclarationError.class));
|
||||
} catch (BeanDefinitionParsingException ex) {
|
||||
assertTrue(ex.getMessage().contains("cannot be used on a singleton/prototype bean"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +240,8 @@ public class ScopingTests {
|
|||
@Configuration
|
||||
static class ScopeTestConfiguration {
|
||||
|
||||
@Bean(scope = StandardScopes.SESSION)
|
||||
@Bean
|
||||
@org.springframework.context.annotation.Scope(StandardScopes.SESSION)
|
||||
@ScopedProxy
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
|
|
@ -326,21 +326,24 @@ public class ScopingTests {
|
|||
|
||||
@Configuration
|
||||
public static class ScopedConfigurationClass {
|
||||
@Bean(scope = SCOPE)
|
||||
@Bean
|
||||
@org.springframework.context.annotation.Scope(SCOPE)
|
||||
public TestBean scopedClass() {
|
||||
TestBean tb = new TestBean();
|
||||
tb.setName(flag);
|
||||
return tb;
|
||||
}
|
||||
|
||||
@Bean(scope = SCOPE)
|
||||
@Bean
|
||||
@org.springframework.context.annotation.Scope(SCOPE)
|
||||
public ITestBean scopedInterface() {
|
||||
TestBean tb = new TestBean();
|
||||
tb.setName(flag);
|
||||
return tb;
|
||||
}
|
||||
|
||||
@Bean(scope = SCOPE)
|
||||
@Bean
|
||||
@org.springframework.context.annotation.Scope(SCOPE)
|
||||
@ScopedProxy(proxyTargetClass = false)
|
||||
public ITestBean scopedProxyInterface() {
|
||||
TestBean tb = new TestBean();
|
||||
|
|
@ -349,7 +352,8 @@ public class ScopingTests {
|
|||
}
|
||||
|
||||
@ScopedProxy
|
||||
@Bean(scope = SCOPE)
|
||||
@Bean
|
||||
@org.springframework.context.annotation.Scope(SCOPE)
|
||||
public TestBean scopedProxyClass() {
|
||||
TestBean tb = new TestBean();
|
||||
tb.setName(flag);
|
||||
|
|
|
|||
Loading…
Reference in New Issue