diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/BeanDefinitionRegistrar.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanDefinitionRegistrar.java
similarity index 95%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/BeanDefinitionRegistrar.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/BeanDefinitionRegistrar.java
index 64e62fb6d6..31002e64ff 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/BeanDefinitionRegistrar.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanDefinitionRegistrar.java
@@ -1,4 +1,4 @@
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import java.lang.reflect.Method;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/annotation/Configuration.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/Configuration.java
similarity index 98%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/annotation/Configuration.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/Configuration.java
index 5fe2f126b4..832ba30e9d 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/annotation/Configuration.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/Configuration.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.annotation;
+package org.springframework.config.java;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ConfigurationClass.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationClass.java
similarity index 99%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/ConfigurationClass.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationClass.java
index 7dcfcae4a8..732e481969 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ConfigurationClass.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationClass.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import static java.lang.String.*;
@@ -24,7 +24,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.springframework.config.java.annotation.Configuration;
import org.springframework.util.Assert;
import sun.security.x509.Extension;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ConfigurationModel.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationModel.java
similarity index 98%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/ConfigurationModel.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationModel.java
index 4d3394d8b6..5c813c8a78 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ConfigurationModel.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationModel.java
@@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import static java.lang.String.*;
import java.util.ArrayList;
import java.util.List;
-import org.springframework.config.java.annotation.Configuration;
/**
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/Factory.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/Factory.java
similarity index 97%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/Factory.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/Factory.java
index 10cb299e2e..bea48c6d2e 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/Factory.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/Factory.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/MalformedJavaConfigurationException.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/MalformedJavaConfigurationException.java
similarity index 97%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/MalformedJavaConfigurationException.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/MalformedJavaConfigurationException.java
index 00788515bc..a331ccee10 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/MalformedJavaConfigurationException.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/MalformedJavaConfigurationException.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ModelClass.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ModelClass.java
similarity index 97%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/ModelClass.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/ModelClass.java
index f041ea412a..5f7fcc657b 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ModelClass.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ModelClass.java
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import org.springframework.beans.BeanMetadataElement;
-import org.springframework.config.java.annotation.Configuration;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ModelMethod.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ModelMethod.java
similarity index 99%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/ModelMethod.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/ModelMethod.java
index f410ff6851..d5b667cc83 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/ModelMethod.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ModelMethod.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import static java.lang.String.*;
import static org.springframework.config.java.Util.*;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/UsageError.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/UsageError.java
similarity index 95%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/UsageError.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/UsageError.java
index c431f46828..90767b6a41 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/UsageError.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/UsageError.java
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.config.java.model;
+package org.springframework.config.java;
-import org.springframework.config.java.annotation.Configuration;
/**
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/Validatable.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/Validatable.java
similarity index 87%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/Validatable.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/Validatable.java
index 6d0397e113..a5ce87e318 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/Validatable.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/Validatable.java
@@ -1,4 +1,4 @@
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import java.util.List;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/Validator.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/Validator.java
similarity index 83%
rename from org.springframework.config.java/src/main/java/org/springframework/config/java/model/Validator.java
rename to org.springframework.config.java/src/main/java/org/springframework/config/java/Validator.java
index 40e8ed6796..7246ee0ee7 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/model/Validator.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/Validator.java
@@ -1,4 +1,4 @@
-package org.springframework.config.java.model;
+package org.springframework.config.java;
import java.util.List;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/Bean.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/Bean.java
index 45075810be..a5872313f6 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/Bean.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/Bean.java
@@ -26,13 +26,13 @@ import java.util.List;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.config.java.annotation.Configuration;
-import org.springframework.config.java.model.ConfigurationClass;
-import org.springframework.config.java.model.ConfigurationModel;
-import org.springframework.config.java.model.Factory;
-import org.springframework.config.java.model.ModelMethod;
-import org.springframework.config.java.model.UsageError;
-import org.springframework.config.java.model.Validator;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationClass;
+import org.springframework.config.java.ConfigurationModel;
+import org.springframework.config.java.Factory;
+import org.springframework.config.java.ModelMethod;
+import org.springframework.config.java.UsageError;
+import org.springframework.config.java.Validator;
/**
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/BeanRegistrar.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/BeanRegistrar.java
index b9812e81b9..1485371f29 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/BeanRegistrar.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ext/BeanRegistrar.java
@@ -13,12 +13,12 @@ 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.config.java.annotation.Configuration;
-import org.springframework.config.java.model.BeanDefinitionRegistrar;
-import org.springframework.config.java.model.ConfigurationClass;
-import org.springframework.config.java.model.MalformedJavaConfigurationException;
-import org.springframework.config.java.model.ModelMethod;
-import org.springframework.config.java.model.UsageError;
+import org.springframework.config.java.BeanDefinitionRegistrar;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationClass;
+import org.springframework.config.java.MalformedJavaConfigurationException;
+import org.springframework.config.java.ModelMethod;
+import org.springframework.config.java.UsageError;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/AddAnnotationAdapter.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/AddAnnotationAdapter.java
index 96ae3bfefe..688ae7333d 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/AddAnnotationAdapter.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/AddAnnotationAdapter.java
@@ -28,7 +28,9 @@ import org.objectweb.asm.MethodVisitor;
/**
* Transforms a class by adding bytecode for a class-level annotation.
* Checks to ensure that the desired annotation is not already present
- * before adding.
+ * before adding. Used by {@link ConfigurationEnhancer} to dynamically add
+ * an {@link org.aspectj.lang.Aspect} annotation to an enhanced Configuration
+ * subclass.
*
* This class was originally adapted from examples the ASM 3.0 documentation.
*
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/CglibConfigurationEnhancer.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/CglibConfigurationEnhancer.java
deleted file mode 100644
index 758f77d673..0000000000
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/CglibConfigurationEnhancer.java
+++ /dev/null
@@ -1,237 +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.internal.enhancement;
-
-import static java.lang.String.*;
-import static org.springframework.config.java.Util.*;
-import static org.springframework.util.Assert.*;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-
-import net.sf.cglib.core.DefaultGeneratorStrategy;
-import net.sf.cglib.proxy.Callback;
-import net.sf.cglib.proxy.CallbackFilter;
-import net.sf.cglib.proxy.Enhancer;
-import net.sf.cglib.proxy.NoOp;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.objectweb.asm.ClassAdapter;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassWriter;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.config.java.annotation.Configuration;
-import org.springframework.config.java.model.BeanDefinitionRegistrar;
-import org.springframework.config.java.model.ConfigurationClass;
-import org.springframework.config.java.model.ConfigurationModel;
-import org.springframework.config.java.model.ModelMethod;
-
-
-
-/**
- * Enhances {@link Configuration} classes by generating a CGLIB subclass capable of
- * interacting with the Spring container to respect bean semantics.
- *
- * @see #enhance(String)
- *
- * @author Chris Beams
- */
-public class CglibConfigurationEnhancer implements ConfigurationEnhancer {
-
- private static final Log log = LogFactory.getLog(CglibConfigurationEnhancer.class);
-
- private final ArrayList> callbackTypes =
- new ArrayList>();
-
- private final LinkedHashSet handlers =
- new LinkedHashSet();
-
- private final ArrayList callbackInstances =
- new ArrayList();
-
- private final CallbackFilter callbackFilter =
- new CallbackFilter() {
- public int accept(Method candidateMethod) {
- Iterator iter = handlers.iterator();
- for(int i=0; iter.hasNext(); i++)
- if(iter.next().accepts(candidateMethod))
- return i;
-
- throw new IllegalStateException(format("No registered handler is capable of " +
- "handling method [%s]. Perhaps you forgot to register a catch-all registrar?",
- candidateMethod.getName()));
- }
- };
-
-
- /**
- * Creates a new {@link CglibConfigurationEnhancer} instance.
- */
- public CglibConfigurationEnhancer(DefaultListableBeanFactory beanFactory, ConfigurationModel model) {
- notNull(beanFactory, "beanFactory must be non-null");
- notNull(model, "model must be non-null");
-
- populateHandlersAndCallbacks(beanFactory, model);
- }
-
-
- /**
- * Reads the contents of {@code model} in order to populate {@link #handlers},
- * {@link #callbackInstances} and {@link #callbackTypes} appropriately.
- *
- * @see #callbackFilter
- */
- private void populateHandlersAndCallbacks(DefaultListableBeanFactory beanFactory, ConfigurationModel model) {
-
- for (ConfigurationClass configClass : model.getAllConfigurationClasses()) {
- for (ModelMethod method : configClass.getMethods()) {
- handlers.add(method.getRegistrar());
-
- Callback callback = method.getCallback();
-
- if(callback instanceof BeanFactoryAware)
- ((BeanFactoryAware)callback).setBeanFactory(beanFactory);
-
- callbackInstances.add(callback);
- }
- }
-
- handlers.add(new InitializingBeanRegistrar());
- callbackInstances.add(new InitializingBeanCallback(beanFactory));
-
- // register a 'catch-all' registrar
- handlers.add(new BeanDefinitionRegistrar() {
-
- public boolean accepts(Method method) {
- return true;
- }
-
- public void register(ModelMethod method, BeanDefinitionRegistry registry) {
- // no-op
- }
- });
- callbackInstances.add(NoOp.INSTANCE);
-
- for(Callback callback : callbackInstances)
- callbackTypes.add(callback.getClass());
- }
-
-
- /**
- * Loads the specified class and generates a CGLIB subclass of it equipped with container-aware
- * callbacks capable of respecting scoping and other bean semantics.
- */
- public String enhance(String configClassName) {
- if (log.isInfoEnabled())
- log.info("Enhancing " + configClassName);
-
- Class> superclass = loadRequiredClass(configClassName);
-
- Class> subclass = createClass(newEnhancer(superclass), superclass);
-
- subclass = nestOneClassDeeperIfAspect(superclass, subclass);
-
- if (log.isInfoEnabled())
- log.info(format("Successfully enhanced %s; enhanced class name is: %s",
- configClassName, subclass.getName()));
-
- return subclass.getName();
- }
-
- /**
- * Creates a new CGLIB {@link Enhancer} instance.
- */
- private Enhancer newEnhancer(Class> superclass) {
- Enhancer enhancer = new Enhancer();
-
- // because callbackFilter and callbackTypes are dynamically populated
- // there's no opportunity for caching. This does not appear to be causing
- // any performance problem.
- enhancer.setUseCache(false);
-
- enhancer.setSuperclass(superclass);
- enhancer.setInterfaces(new Class>[]{InitializingBean.class});
- enhancer.setUseFactory(false);
- enhancer.setCallbackFilter(callbackFilter);
- enhancer.setCallbackTypes(callbackTypes.toArray(new Class>[]{}));
-
- return enhancer;
- }
-
- /**
- * Uses enhancer to generate a subclass of superclass, ensuring that
- * {@link #callbackInstances} are registered for the new subclass.
- */
- private Class> createClass(Enhancer enhancer, Class> superclass) {
- Class> subclass = enhancer.createClass();
-
- // see #registerThreadLocalCleanupBeanDefinition
- Enhancer.registerCallbacks(subclass, callbackInstances.toArray(new Callback[] {}));
- //Enhancer.registerStaticCallbacks(subclass, callbackInstances.toArray(new Callback[] {}));
-
- return subclass;
- }
-
- /**
- * Works around a constraint imposed by the AspectJ 5 annotation-style programming model. See
- * comments inline for detail.
- *
- * @return original subclass instance unless superclass is annnotated with @Aspect, in which
- * case a subclass of the subclass is returned
- */
- private Class> nestOneClassDeeperIfAspect(Class> superclass, Class> origSubclass) {
- boolean superclassIsAnAspect = false;
-
- // check for @Aspect by name rather than by class literal to avoid
- // requiring AspectJ as a runtime dependency.
- for(Annotation anno : superclass.getAnnotations())
- if(anno.annotationType().getName().equals("org.aspectj.lang.annotation.Aspect"))
- superclassIsAnAspect = true;
-
- if(!superclassIsAnAspect)
- return origSubclass;
-
- // the superclass is annotated with AspectJ's @Aspect.
- // this means that we must create a subclass of the subclass
- // in order to avoid some guard logic in Spring core that disallows
- // extending a concrete aspect class.
- Enhancer enhancer = newEnhancer(origSubclass);
- enhancer.setStrategy(new DefaultGeneratorStrategy() {
- @Override
- protected byte[] transform(byte[] b) throws Exception {
- ClassWriter writer = new ClassWriter(false);
- ClassAdapter adapter =
- new AddAnnotationAdapter(writer, "Lorg/aspectj/lang/annotation/Aspect;");
- ClassReader reader = new ClassReader(b);
- reader.accept(adapter, false);
- return writer.toByteArray();
- }
- });
-
- // create a subclass of the original subclass
- Class> newSubclass = createClass(enhancer, origSubclass);
-
- return newSubclass;
- }
-
-}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java
index 10c2184d47..8175ee4ac5 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java
@@ -15,10 +15,223 @@
*/
package org.springframework.config.java.internal.enhancement;
+import static java.lang.String.*;
+import static org.springframework.config.java.Util.*;
+import static org.springframework.util.Assert.*;
-/** TODO: JAVADOC */
-public interface ConfigurationEnhancer {
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
- String enhance(String configClassName);
+import net.sf.cglib.core.DefaultGeneratorStrategy;
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.CallbackFilter;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.NoOp;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.config.java.BeanDefinitionRegistrar;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationClass;
+import org.springframework.config.java.ConfigurationModel;
+import org.springframework.config.java.ModelMethod;
+
+
+
+/**
+ * Enhances {@link Configuration} classes by generating a CGLIB subclass capable of
+ * interacting with the Spring container to respect bean semantics.
+ *
+ * @see #enhance(String)
+ *
+ * @author Chris Beams
+ */
+public class ConfigurationEnhancer {
+
+ private static final Log log = LogFactory.getLog(ConfigurationEnhancer.class);
+
+ private final ArrayList> callbackTypes =
+ new ArrayList>();
+
+ private final LinkedHashSet registrars =
+ new LinkedHashSet();
+
+ private final ArrayList callbackInstances =
+ new ArrayList();
+
+ private final CallbackFilter callbackFilter =
+ new CallbackFilter() {
+ public int accept(Method candidateMethod) {
+ Iterator iter = registrars.iterator();
+ for(int i=0; iter.hasNext(); i++)
+ if(iter.next().accepts(candidateMethod))
+ return i;
+
+ throw new IllegalStateException(format("No registrar is capable of " +
+ "handling method [%s]. Perhaps you forgot to add a catch-all registrar?",
+ candidateMethod.getName()));
+ }
+ };
+
+
+ /**
+ * Creates a new {@link ConfigurationEnhancer} instance.
+ */
+ public ConfigurationEnhancer(DefaultListableBeanFactory beanFactory, ConfigurationModel model) {
+ notNull(beanFactory, "beanFactory must be non-null");
+ notNull(model, "model must be non-null");
+
+ populateHandlersAndCallbacks(beanFactory, model);
+ }
+
+
+ /**
+ * Reads the contents of {@code model} in order to populate {@link #registrars},
+ * {@link #callbackInstances} and {@link #callbackTypes} appropriately.
+ *
+ * @see #callbackFilter
+ */
+ private void populateHandlersAndCallbacks(DefaultListableBeanFactory beanFactory, ConfigurationModel model) {
+
+ for (ConfigurationClass configClass : model.getAllConfigurationClasses()) {
+ for (ModelMethod method : configClass.getMethods()) {
+ registrars.add(method.getRegistrar());
+
+ Callback callback = method.getCallback();
+
+ if(callback instanceof BeanFactoryAware)
+ ((BeanFactoryAware)callback).setBeanFactory(beanFactory);
+
+ callbackInstances.add(callback);
+ }
+ }
+
+ registrars.add(new InitializingBeanRegistrar());
+ callbackInstances.add(new InitializingBeanCallback(beanFactory));
+
+ // register a 'catch-all' registrar
+ registrars.add(new BeanDefinitionRegistrar() {
+
+ public boolean accepts(Method method) {
+ return true;
+ }
+
+ public void register(ModelMethod method, BeanDefinitionRegistry registry) {
+ // no-op
+ }
+ });
+ callbackInstances.add(NoOp.INSTANCE);
+
+ for(Callback callback : callbackInstances)
+ callbackTypes.add(callback.getClass());
+ }
+
+
+ /**
+ * Loads the specified class and generates a CGLIB subclass of it equipped with container-aware
+ * callbacks capable of respecting scoping and other bean semantics.
+ */
+ public String enhance(String configClassName) {
+ if (log.isInfoEnabled())
+ log.info("Enhancing " + configClassName);
+
+ Class> superclass = loadRequiredClass(configClassName);
+
+ Class> subclass = createClass(newEnhancer(superclass), superclass);
+
+ subclass = nestOneClassDeeperIfAspect(superclass, subclass);
+
+ if (log.isInfoEnabled())
+ log.info(format("Successfully enhanced %s; enhanced class name is: %s",
+ configClassName, subclass.getName()));
+
+ return subclass.getName();
+ }
+
+ /**
+ * Creates a new CGLIB {@link Enhancer} instance.
+ */
+ private Enhancer newEnhancer(Class> superclass) {
+ Enhancer enhancer = new Enhancer();
+
+ // because callbackFilter and callbackTypes are dynamically populated
+ // there's no opportunity for caching. This does not appear to be causing
+ // any performance problem.
+ enhancer.setUseCache(false);
+
+ enhancer.setSuperclass(superclass);
+ enhancer.setInterfaces(new Class>[]{InitializingBean.class});
+ enhancer.setUseFactory(false);
+ enhancer.setCallbackFilter(callbackFilter);
+ enhancer.setCallbackTypes(callbackTypes.toArray(new Class>[]{}));
+
+ return enhancer;
+ }
+
+ /**
+ * Uses enhancer to generate a subclass of superclass, ensuring that
+ * {@link #callbackInstances} are registered for the new subclass.
+ */
+ private Class> createClass(Enhancer enhancer, Class> superclass) {
+ Class> subclass = enhancer.createClass();
+
+ // see #registerThreadLocalCleanupBeanDefinition
+ Enhancer.registerCallbacks(subclass, callbackInstances.toArray(new Callback[] {}));
+ //Enhancer.registerStaticCallbacks(subclass, callbackInstances.toArray(new Callback[] {}));
+
+ return subclass;
+ }
+
+ /**
+ * Works around a constraint imposed by the AspectJ 5 annotation-style programming model. See
+ * comments inline for detail.
+ *
+ * @return original subclass instance unless superclass is annnotated with @Aspect, in which
+ * case a subclass of the subclass is returned
+ */
+ private Class> nestOneClassDeeperIfAspect(Class> superclass, Class> origSubclass) {
+ boolean superclassIsAnAspect = false;
+
+ // check for @Aspect by name rather than by class literal to avoid
+ // requiring AspectJ as a runtime dependency.
+ for(Annotation anno : superclass.getAnnotations())
+ if(anno.annotationType().getName().equals("org.aspectj.lang.annotation.Aspect"))
+ superclassIsAnAspect = true;
+
+ if(!superclassIsAnAspect)
+ return origSubclass;
+
+ // the superclass is annotated with AspectJ's @Aspect.
+ // this means that we must create a subclass of the subclass
+ // in order to avoid some guard logic in Spring core that disallows
+ // extending a concrete aspect class.
+ Enhancer enhancer = newEnhancer(origSubclass);
+ enhancer.setStrategy(new DefaultGeneratorStrategy() {
+ @Override
+ protected byte[] transform(byte[] b) throws Exception {
+ ClassWriter writer = new ClassWriter(false);
+ ClassAdapter adapter =
+ new AddAnnotationAdapter(writer, "Lorg/aspectj/lang/annotation/Aspect;");
+ ClassReader reader = new ClassReader(b);
+ reader.accept(adapter, false);
+ return writer.toByteArray();
+ }
+ });
+
+ // create a subclass of the original subclass
+ Class> newSubclass = createClass(enhancer, origSubclass);
+
+ return newSubclass;
+ }
+
}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/InitializingBeanRegistrar.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/InitializingBeanRegistrar.java
index 692171c21e..d4428d490e 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/InitializingBeanRegistrar.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/InitializingBeanRegistrar.java
@@ -18,8 +18,8 @@ package org.springframework.config.java.internal.enhancement;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.config.java.model.BeanDefinitionRegistrar;
-import org.springframework.config.java.model.ModelMethod;
+import org.springframework.config.java.BeanDefinitionRegistrar;
+import org.springframework.config.java.ModelMethod;
class InitializingBeanRegistrar implements BeanDefinitionRegistrar {
public boolean accepts(Method method) {
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/AsmJavaConfigBeanDefinitionReader.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/AsmJavaConfigBeanDefinitionReader.java
index 2fb2e8d3ac..8df795743b 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/AsmJavaConfigBeanDefinitionReader.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/AsmJavaConfigBeanDefinitionReader.java
@@ -25,13 +25,13 @@ 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.annotation.Configuration;
+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.config.java.model.ConfigurationModel;
-import org.springframework.config.java.model.MalformedJavaConfigurationException;
-import org.springframework.config.java.model.UsageError;
import org.springframework.core.io.ClassPathResource;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/ConfigurationModelBeanDefinitionReader.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/ConfigurationModelBeanDefinitionReader.java
index 9873db70c7..f79e4447f5 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/ConfigurationModelBeanDefinitionReader.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/factory/support/ConfigurationModelBeanDefinitionReader.java
@@ -32,11 +32,11 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.config.java.annotation.Configuration;
-import org.springframework.config.java.model.ConfigurationClass;
-import org.springframework.config.java.model.ConfigurationModel;
-import org.springframework.config.java.model.Factory;
-import org.springframework.config.java.model.ModelMethod;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationClass;
+import org.springframework.config.java.ConfigurationModel;
+import org.springframework.config.java.Factory;
+import org.springframework.config.java.ModelMethod;
import org.springframework.config.java.plugin.Extension;
import org.springframework.config.java.plugin.ExtensionAnnotationBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationUtils;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/ConfigurationParser.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/ConfigurationParser.java
index fe7523325e..53eb4c91d2 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/ConfigurationParser.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/ConfigurationParser.java
@@ -15,8 +15,8 @@
*/
package org.springframework.config.java.internal.parsing;
-import org.springframework.config.java.annotation.Configuration;
-import org.springframework.config.java.model.ConfigurationModel;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationModel;
/**
@@ -26,7 +26,7 @@ import org.springframework.config.java.model.ConfigurationModel;
* from the process of registering bean definitions based on the content of that class.
*
* @see org.springframework.config.java.internal.parsing.asm.AsmConfigurationParser
- * @see org.springframework.config.java.model.ConfigurationModel
+ * @see org.springframework.config.java.ConfigurationModel
* @see org.springframework.config.java.internal.factory.support.ConfigurationModelBeanDefinitionReader
*
* @author Chris Beams
@@ -39,7 +39,7 @@ public interface ConfigurationParser {
* @param configurationSource representation of a Configuration class, may be java.lang.Class,
* ASM representation or otherwise
*
- * @see org.springframework.config.java.annotation.Configuration
+ * @see org.springframework.config.java.Configuration
*/
void parse(Object configurationSource);
@@ -52,7 +52,7 @@ public interface ConfigurationParser {
* @param configurationId name of this configuration class, probably corresponding to a
* bean id
*
- * @see org.springframework.config.java.annotation.Configuration
+ * @see org.springframework.config.java.Configuration
* @see org.springframework.config.java.process.ConfigurationPostProcessor
*/
void parse(Object configurationSource, String configurationId);
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/AsmConfigurationParser.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/AsmConfigurationParser.java
index f6f76cad1e..62d9128a5d 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/AsmConfigurationParser.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/AsmConfigurationParser.java
@@ -18,10 +18,10 @@ package org.springframework.config.java.internal.parsing.asm;
import org.objectweb.asm.ClassReader;
-import org.springframework.config.java.annotation.Configuration;
+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.config.java.model.ConfigurationClass;
-import org.springframework.config.java.model.ConfigurationModel;
import org.springframework.util.Assert;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassMethodVisitor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassMethodVisitor.java
index 2b89e911c2..4cd2155459 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassMethodVisitor.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassMethodVisitor.java
@@ -28,11 +28,11 @@ import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.Opcodes;
-import org.springframework.config.java.annotation.Configuration;
-import org.springframework.config.java.model.ConfigurationClass;
-import org.springframework.config.java.model.Factory;
-import org.springframework.config.java.model.ModelClass;
-import org.springframework.config.java.model.ModelMethod;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationClass;
+import org.springframework.config.java.Factory;
+import org.springframework.config.java.ModelClass;
+import org.springframework.config.java.ModelMethod;
/**
* Visits a single method declared in a given {@link Configuration} class. Determines whether the
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassVisitor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassVisitor.java
index a5a5d63ffe..6e0d93041b 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassVisitor.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/parsing/asm/ConfigurationClassVisitor.java
@@ -29,9 +29,9 @@ import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
-import org.springframework.config.java.annotation.Configuration;
-import org.springframework.config.java.model.ConfigurationClass;
-import org.springframework.config.java.model.ConfigurationModel;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationClass;
+import org.springframework.config.java.ConfigurationModel;
import org.springframework.config.java.plugin.Extension;
import org.springframework.util.ClassUtils;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/process/InternalConfigurationPostProcessor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/process/InternalConfigurationPostProcessor.java
index 20479c1035..caf916a3e2 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/process/InternalConfigurationPostProcessor.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/process/InternalConfigurationPostProcessor.java
@@ -27,11 +27,10 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.config.java.annotation.Configuration;
-import org.springframework.config.java.internal.enhancement.CglibConfigurationEnhancer;
+import org.springframework.config.java.Configuration;
+import org.springframework.config.java.ConfigurationModel;
import org.springframework.config.java.internal.enhancement.ConfigurationEnhancer;
import org.springframework.config.java.internal.factory.support.AsmJavaConfigBeanDefinitionReader;
-import org.springframework.config.java.model.ConfigurationModel;
import org.springframework.config.java.process.ConfigurationPostProcessor;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ClassUtils;
@@ -48,11 +47,15 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
* necessary to fulfill JavaConfig requirements.
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ if(!(beanFactory instanceof DefaultListableBeanFactory))
+ throw new IllegalStateException("beanFactory must be of type "
+ + DefaultListableBeanFactory.class.getSimpleName());
+
ConfigurationModel model = new ConfigurationModel();
parseAnyConfigurationClasses(beanFactory, model);
- enhanceAnyConfigurationClasses(beanFactory, model);
+ enhanceAnyConfigurationClasses((DefaultListableBeanFactory) beanFactory, model);
}
private void parseAnyConfigurationClasses(ConfigurableListableBeanFactory beanFactory, ConfigurationModel model) {
@@ -84,14 +87,9 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
* @see ConfigurationEnhancer
* @see BeanFactoryPostProcessor
*/
- private void enhanceAnyConfigurationClasses(ConfigurableListableBeanFactory clbf, ConfigurationModel model) {
- if(!(clbf instanceof DefaultListableBeanFactory))
- throw new IllegalStateException("beanFactory must be of type "
- + DefaultListableBeanFactory.class.getSimpleName());
+ private void enhanceAnyConfigurationClasses(DefaultListableBeanFactory beanFactory, ConfigurationModel model) {
- DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)clbf;
-
- ConfigurationEnhancer enhancer = new CglibConfigurationEnhancer(beanFactory, model);
+ ConfigurationEnhancer enhancer = new ConfigurationEnhancer(beanFactory, model);
int configClassesEnhanced = 0;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/process/ConfigurationPostProcessor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/process/ConfigurationPostProcessor.java
index d763025e6c..f0ee1d88d0 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/process/ConfigurationPostProcessor.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/process/ConfigurationPostProcessor.java
@@ -19,7 +19,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.config.java.annotation.Configuration;
+import org.springframework.config.java.Configuration;
import org.springframework.config.java.internal.process.InternalConfigurationPostProcessor;
import org.springframework.core.Ordered;
diff --git a/org.springframework.config.java/src/test/java/test/basic/AutowiredConfigurationTests.java b/org.springframework.config.java/src/test/java/test/basic/AutowiredConfigurationTests.java
index 2d058a409c..41c08c91f9 100644
--- a/org.springframework.config.java/src/test/java/test/basic/AutowiredConfigurationTests.java
+++ b/org.springframework.config.java/src/test/java/test/basic/AutowiredConfigurationTests.java
@@ -5,7 +5,8 @@ import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.config.java.annotation.Configuration;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.config.java.Configuration;
import org.springframework.config.java.ext.Bean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -36,4 +37,26 @@ public class AutowiredConfigurationTests {
public @Bean Colour colour() { return Colour.RED; }
}
+
+
+ public @Test void testValueInjection() {
+ System.setProperty("myProp", "foo");
+
+ ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext(
+ "ValueInjectionTests.xml", AutowiredConfigurationTests.class);
+
+ TestBean testBean = factory.getBean("testBean", TestBean.class);
+ assertThat(testBean.getName(), equalTo("foo"));
+ }
+
+ @Configuration
+ static class ValueConfig {
+
+ @Value("#{systemProperties.myProp}")
+ private String name = "default";
+
+ public @Bean TestBean testBean() {
+ return new TestBean(name);
+ }
+ }
}
diff --git a/org.springframework.config.java/src/test/java/test/basic/BasicTests.java b/org.springframework.config.java/src/test/java/test/basic/BasicTests.java
index a9c60041e8..a1927f14f0 100644
--- a/org.springframework.config.java/src/test/java/test/basic/BasicTests.java
+++ b/org.springframework.config.java/src/test/java/test/basic/BasicTests.java
@@ -9,7 +9,7 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.config.java.annotation.Configuration;
+import org.springframework.config.java.Configuration;
import org.springframework.config.java.ext.Bean;
import org.springframework.config.java.process.ConfigurationPostProcessor;
import org.springframework.config.java.util.DefaultScopes;
diff --git a/org.springframework.config.java/src/test/java/test/basic/ValueInjectionTests.xml b/org.springframework.config.java/src/test/java/test/basic/ValueInjectionTests.xml
new file mode 100644
index 0000000000..78f8a6a7de
--- /dev/null
+++ b/org.springframework.config.java/src/test/java/test/basic/ValueInjectionTests.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+