+ 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;
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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.*;
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
|
@ -1,4 +1,4 @@
|
|||
package org.springframework.config.java.model;
|
||||
package org.springframework.config.java;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.springframework.config.java.model;
|
||||
package org.springframework.config.java;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
* <p/>
|
||||
* 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;
|
||||
|
||||
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<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 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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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