+ Further repackaging and consolidation
+ Tested compatibility with @Value (works, but noticed and filed an unrelated-to-javaconfig improvement. See SPR-5530)
This commit is contained in:
parent
2689751c2b
commit
d4fdad2202
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.annotation;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
|
|
||||||
import static java.lang.String.*;
|
import static java.lang.String.*;
|
||||||
|
@ -24,7 +24,6 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import sun.security.x509.Extension;
|
import sun.security.x509.Extension;
|
|
@ -13,14 +13,13 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import static java.lang.String.*;
|
import static java.lang.String.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
|
@ -13,10 +13,9 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
import org.springframework.beans.BeanMetadataElement;
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import static java.lang.String.*;
|
import static java.lang.String.*;
|
||||||
import static org.springframework.config.java.Util.*;
|
import static org.springframework.config.java.Util.*;
|
|
@ -13,9 +13,8 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.config.java.model;
|
package org.springframework.config.java;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -26,13 +26,13 @@ import java.util.List;
|
||||||
import org.springframework.beans.factory.annotation.Autowire;
|
import org.springframework.beans.factory.annotation.Autowire;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
import org.springframework.config.java.Configuration;
|
||||||
import org.springframework.config.java.model.ConfigurationClass;
|
import org.springframework.config.java.ConfigurationClass;
|
||||||
import org.springframework.config.java.model.ConfigurationModel;
|
import org.springframework.config.java.ConfigurationModel;
|
||||||
import org.springframework.config.java.model.Factory;
|
import org.springframework.config.java.Factory;
|
||||||
import org.springframework.config.java.model.ModelMethod;
|
import org.springframework.config.java.ModelMethod;
|
||||||
import org.springframework.config.java.model.UsageError;
|
import org.springframework.config.java.UsageError;
|
||||||
import org.springframework.config.java.model.Validator;
|
import org.springframework.config.java.Validator;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,12 +13,12 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
import org.springframework.config.java.BeanDefinitionRegistrar;
|
||||||
import org.springframework.config.java.model.BeanDefinitionRegistrar;
|
import org.springframework.config.java.Configuration;
|
||||||
import org.springframework.config.java.model.ConfigurationClass;
|
import org.springframework.config.java.ConfigurationClass;
|
||||||
import org.springframework.config.java.model.MalformedJavaConfigurationException;
|
import org.springframework.config.java.MalformedJavaConfigurationException;
|
||||||
import org.springframework.config.java.model.ModelMethod;
|
import org.springframework.config.java.ModelMethod;
|
||||||
import org.springframework.config.java.model.UsageError;
|
import org.springframework.config.java.UsageError;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,9 @@ import org.objectweb.asm.MethodVisitor;
|
||||||
/**
|
/**
|
||||||
* Transforms a class by adding bytecode for a class-level annotation.
|
* Transforms a class by adding bytecode for a class-level annotation.
|
||||||
* Checks to ensure that the desired annotation is not already present
|
* 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.
|
||||||
* <p/>
|
* <p/>
|
||||||
* This class was originally adapted from examples the ASM 3.0 documentation.
|
* This class was originally adapted from examples the ASM 3.0 documentation.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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<Class<? extends Callback>> callbackTypes =
|
|
||||||
new ArrayList<Class<? extends Callback>>();
|
|
||||||
|
|
||||||
private final LinkedHashSet<BeanDefinitionRegistrar> handlers =
|
|
||||||
new LinkedHashSet<BeanDefinitionRegistrar>();
|
|
||||||
|
|
||||||
private final ArrayList<Callback> callbackInstances =
|
|
||||||
new ArrayList<Callback>();
|
|
||||||
|
|
||||||
private final CallbackFilter callbackFilter =
|
|
||||||
new CallbackFilter() {
|
|
||||||
public int accept(Method candidateMethod) {
|
|
||||||
Iterator<BeanDefinitionRegistrar> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -15,10 +15,223 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.internal.enhancement;
|
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 */
|
import java.lang.annotation.Annotation;
|
||||||
public interface ConfigurationEnhancer {
|
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<Class<? extends Callback>> callbackTypes =
|
||||||
|
new ArrayList<Class<? extends Callback>>();
|
||||||
|
|
||||||
|
private final LinkedHashSet<BeanDefinitionRegistrar> registrars =
|
||||||
|
new LinkedHashSet<BeanDefinitionRegistrar>();
|
||||||
|
|
||||||
|
private final ArrayList<Callback> callbackInstances =
|
||||||
|
new ArrayList<Callback>();
|
||||||
|
|
||||||
|
private final CallbackFilter callbackFilter =
|
||||||
|
new CallbackFilter() {
|
||||||
|
public int accept(Method candidateMethod) {
|
||||||
|
Iterator<BeanDefinitionRegistrar> 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ package org.springframework.config.java.internal.enhancement;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.config.java.model.BeanDefinitionRegistrar;
|
import org.springframework.config.java.BeanDefinitionRegistrar;
|
||||||
import org.springframework.config.java.model.ModelMethod;
|
import org.springframework.config.java.ModelMethod;
|
||||||
|
|
||||||
class InitializingBeanRegistrar implements BeanDefinitionRegistrar {
|
class InitializingBeanRegistrar implements BeanDefinitionRegistrar {
|
||||||
public boolean accepts(Method method) {
|
public boolean accepts(Method method) {
|
||||||
|
|
|
@ -25,13 +25,13 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
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.ConfigurationParser;
|
||||||
import org.springframework.config.java.internal.parsing.asm.AsmConfigurationParser;
|
import org.springframework.config.java.internal.parsing.asm.AsmConfigurationParser;
|
||||||
import org.springframework.config.java.internal.parsing.asm.AsmUtils;
|
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;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,11 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
import org.springframework.config.java.Configuration;
|
||||||
import org.springframework.config.java.model.ConfigurationClass;
|
import org.springframework.config.java.ConfigurationClass;
|
||||||
import org.springframework.config.java.model.ConfigurationModel;
|
import org.springframework.config.java.ConfigurationModel;
|
||||||
import org.springframework.config.java.model.Factory;
|
import org.springframework.config.java.Factory;
|
||||||
import org.springframework.config.java.model.ModelMethod;
|
import org.springframework.config.java.ModelMethod;
|
||||||
import org.springframework.config.java.plugin.Extension;
|
import org.springframework.config.java.plugin.Extension;
|
||||||
import org.springframework.config.java.plugin.ExtensionAnnotationBeanDefinitionRegistrar;
|
import org.springframework.config.java.plugin.ExtensionAnnotationBeanDefinitionRegistrar;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.config.java.internal.parsing;
|
package org.springframework.config.java.internal.parsing;
|
||||||
|
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
import org.springframework.config.java.Configuration;
|
||||||
import org.springframework.config.java.model.ConfigurationModel;
|
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.
|
* 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.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
|
* @see org.springframework.config.java.internal.factory.support.ConfigurationModelBeanDefinitionReader
|
||||||
*
|
*
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
@ -39,7 +39,7 @@ public interface ConfigurationParser {
|
||||||
* @param configurationSource representation of a Configuration class, may be java.lang.Class,
|
* @param configurationSource representation of a Configuration class, may be java.lang.Class,
|
||||||
* ASM representation or otherwise
|
* ASM representation or otherwise
|
||||||
*
|
*
|
||||||
* @see org.springframework.config.java.annotation.Configuration
|
* @see org.springframework.config.java.Configuration
|
||||||
*/
|
*/
|
||||||
void parse(Object configurationSource);
|
void parse(Object configurationSource);
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public interface ConfigurationParser {
|
||||||
* @param configurationId name of this configuration class, probably corresponding to a
|
* @param configurationId name of this configuration class, probably corresponding to a
|
||||||
* bean id
|
* bean id
|
||||||
*
|
*
|
||||||
* @see org.springframework.config.java.annotation.Configuration
|
* @see org.springframework.config.java.Configuration
|
||||||
* @see org.springframework.config.java.process.ConfigurationPostProcessor
|
* @see org.springframework.config.java.process.ConfigurationPostProcessor
|
||||||
*/
|
*/
|
||||||
void parse(Object configurationSource, String configurationId);
|
void parse(Object configurationSource, String configurationId);
|
||||||
|
|
|
@ -18,10 +18,10 @@ package org.springframework.config.java.internal.parsing.asm;
|
||||||
|
|
||||||
|
|
||||||
import org.objectweb.asm.ClassReader;
|
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.internal.parsing.ConfigurationParser;
|
||||||
import org.springframework.config.java.model.ConfigurationClass;
|
|
||||||
import org.springframework.config.java.model.ConfigurationModel;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,11 @@ import org.objectweb.asm.ClassAdapter;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
import org.objectweb.asm.MethodAdapter;
|
import org.objectweb.asm.MethodAdapter;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
import org.springframework.config.java.Configuration;
|
||||||
import org.springframework.config.java.model.ConfigurationClass;
|
import org.springframework.config.java.ConfigurationClass;
|
||||||
import org.springframework.config.java.model.Factory;
|
import org.springframework.config.java.Factory;
|
||||||
import org.springframework.config.java.model.ModelClass;
|
import org.springframework.config.java.ModelClass;
|
||||||
import org.springframework.config.java.model.ModelMethod;
|
import org.springframework.config.java.ModelMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits a single method declared in a given {@link Configuration} class. Determines whether the
|
* Visits a single method declared in a given {@link Configuration} class. Determines whether the
|
||||||
|
|
|
@ -29,9 +29,9 @@ import org.objectweb.asm.ClassAdapter;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.springframework.config.java.annotation.Configuration;
|
import org.springframework.config.java.Configuration;
|
||||||
import org.springframework.config.java.model.ConfigurationClass;
|
import org.springframework.config.java.ConfigurationClass;
|
||||||
import org.springframework.config.java.model.ConfigurationModel;
|
import org.springframework.config.java.ConfigurationModel;
|
||||||
import org.springframework.config.java.plugin.Extension;
|
import org.springframework.config.java.plugin.Extension;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,10 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
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.internal.enhancement.CglibConfigurationEnhancer;
|
import org.springframework.config.java.ConfigurationModel;
|
||||||
import org.springframework.config.java.internal.enhancement.ConfigurationEnhancer;
|
import org.springframework.config.java.internal.enhancement.ConfigurationEnhancer;
|
||||||
import org.springframework.config.java.internal.factory.support.AsmJavaConfigBeanDefinitionReader;
|
import org.springframework.config.java.internal.factory.support.AsmJavaConfigBeanDefinitionReader;
|
||||||
import org.springframework.config.java.model.ConfigurationModel;
|
|
||||||
import org.springframework.config.java.process.ConfigurationPostProcessor;
|
import org.springframework.config.java.process.ConfigurationPostProcessor;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
@ -48,11 +47,15 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
|
||||||
* necessary to fulfill JavaConfig requirements.
|
* necessary to fulfill JavaConfig requirements.
|
||||||
*/
|
*/
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
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();
|
ConfigurationModel model = new ConfigurationModel();
|
||||||
|
|
||||||
parseAnyConfigurationClasses(beanFactory, model);
|
parseAnyConfigurationClasses(beanFactory, model);
|
||||||
|
|
||||||
enhanceAnyConfigurationClasses(beanFactory, model);
|
enhanceAnyConfigurationClasses((DefaultListableBeanFactory) beanFactory, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseAnyConfigurationClasses(ConfigurableListableBeanFactory beanFactory, ConfigurationModel model) {
|
private void parseAnyConfigurationClasses(ConfigurableListableBeanFactory beanFactory, ConfigurationModel model) {
|
||||||
|
@ -84,14 +87,9 @@ public class InternalConfigurationPostProcessor implements BeanFactoryPostProces
|
||||||
* @see ConfigurationEnhancer
|
* @see ConfigurationEnhancer
|
||||||
* @see BeanFactoryPostProcessor
|
* @see BeanFactoryPostProcessor
|
||||||
*/
|
*/
|
||||||
private void enhanceAnyConfigurationClasses(ConfigurableListableBeanFactory clbf, ConfigurationModel model) {
|
private void enhanceAnyConfigurationClasses(DefaultListableBeanFactory beanFactory, ConfigurationModel model) {
|
||||||
if(!(clbf instanceof DefaultListableBeanFactory))
|
|
||||||
throw new IllegalStateException("beanFactory must be of type "
|
|
||||||
+ DefaultListableBeanFactory.class.getSimpleName());
|
|
||||||
|
|
||||||
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)clbf;
|
ConfigurationEnhancer enhancer = new ConfigurationEnhancer(beanFactory, model);
|
||||||
|
|
||||||
ConfigurationEnhancer enhancer = new CglibConfigurationEnhancer(beanFactory, model);
|
|
||||||
|
|
||||||
int configClassesEnhanced = 0;
|
int configClassesEnhanced = 0;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
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.config.java.internal.process.InternalConfigurationPostProcessor;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.config.java.ext.Bean;
|
||||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
|
||||||
|
@ -36,4 +37,26 @@ public class AutowiredConfigurationTests {
|
||||||
public @Bean Colour colour() { return Colour.RED; }
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
|
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
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.ext.Bean;
|
||||||
import org.springframework.config.java.process.ConfigurationPostProcessor;
|
import org.springframework.config.java.process.ConfigurationPostProcessor;
|
||||||
import org.springframework.config.java.util.DefaultScopes;
|
import org.springframework.config.java.util.DefaultScopes;
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context">
|
||||||
|
|
||||||
|
<context:annotation-config/>
|
||||||
|
|
||||||
|
<bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>
|
||||||
|
|
||||||
|
<bean class="test.basic.AutowiredConfigurationTests$ValueConfig"/>
|
||||||
|
</beans>
|
Loading…
Reference in New Issue