我认为这段代码会有所帮助 -
自动 bean 创建器
import com.google.common.collect.Iterables;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.annotation.Autowired;
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.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AutoBeanDeclarer implements BeanDefinitionRegistryPostProcessor {
private Collection<String> mockedDefinitions;
public AutoBeanDeclarer() {
mockedDefinitions = new ArrayList<String>();
}
private Iterable<Field> findAllAutoWired(Class targetBean) {
List<Field> declaredFields = Arrays.asList(targetBean.getDeclaredFields());
return Iterables.filter(declaredFields, new Predicate<Field>() {
@Override
public boolean apply(Field input) {
return input.isAnnotationPresent(Autowired.class);
}
});
}
private void registerOn(final BeanDefinitionRegistry registry,final String beanName, final Class type){
RootBeanDefinition definition = new RootBeanDefinition(MocksFactory.class);
MutablePropertyValues values = new MutablePropertyValues();
values.addPropertyValue(new PropertyValue("type", type));
definition.setPropertyValues(values);
registry.registerBeanDefinition(beanName, definition);
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
for(String beanName: registry.getBeanDefinitionNames()) {
BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
String beanClassName = beanDefinition.getBeanClassName();
try {
Class beanClass = Class.forName(beanClassName);
for (final Field field : findAllAutoWired(beanClass)) {
String fieldName = field.getName();
boolean invalidType = field.getType().isArray() || field.getType().isPrimitive();
if( invalidType ) {
continue;
}
if( !registry.isBeanNameInUse(fieldName) ) {
registerOn(registry, fieldName, field.getType());
mockedDefinitions.add(fieldName);
// Now field will be available for autowiring.
}
}
} catch (ClassNotFoundException ex) {
Logger.getLogger(AutoBeanDeclarer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for(String beanName: mockedDefinitions) {
if( !beanFactory.containsBean(beanName) ) {
Logger.getLogger(AutoBeanDeclarer.class.getName()).log(Level.SEVERE, "Missing definition %s", beanName);
}
}
}
}
模拟工厂类
import org.mockito.Mockito;
import org.springframework.beans.factory.FactoryBean;
public class MocksFactory implements FactoryBean {
private Class type;// the created object type
public void setType(final Class type) {
this.type = type;
}
@Override
public Object getObject() throws Exception {
return Mockito.mock(type);
}
@Override
public Class getObjectType() {
return type;
}
@Override
public boolean isSingleton() {
return true;
}
}
上下文.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="autoConfigurer" class="....AutoBeanFinder"></bean>
<bean id="targetClass" class="....Target"></bean>
</beans>
在 Target 类中自动装配的所有服务都将被模拟。