【发布时间】:2016-01-17 14:15:40
【问题描述】:
目前我直接在类上使用@CustomAnnotation,并使用 BeanFactoryPostProcessor 将带注释的 bean 的 bean 定义更改为我的需要。
@CustomAnnotation
public class MyBean implements IMybean{
}
@Configuration
public class MyConfiguration {
@Bean
public MyBean myBean(){
return new myBean();
}
}
我想要做的是能够将@CustomAnnotation 放在配置文件的@Bean 方法上,如下所示:
public class MyBean implements IMybean{
}
@Configuration
public class MyConfiguration {
@Bean
@CustomAnnotation
public MyBean myBean(){
return new myBean();
}
}
从 BeanDefinition 中我可以从 beanFactory 中获取,我知道我可以获取工厂 bean 和创建 myBean 的工厂方法,并检查方法上是否有 @CustomAnnotation。
我不确定这样做是否会违反任何 Spring 原则,或者是否是常规操作。
我的初衷是工作。 但是我现在有另一个问题。 我无法使用我想要的类型自动装配来自我想要的工厂的 bean。 存在解决依赖关系的问题。 这是我用来尝试解决问题的测试代码。 test code on github
@Configuration
public class MainConfiguration implements BeanDefinitionRegistryPostProcessor, Ordered {
private SayenBeanDefinitionRegistryPostProcessor sayenBeanDefinitionRegistryPostProcessor = new SayenBeanDefinitionRegistryPostProcessor();
public int getOrder() {
return sayenBeanDefinitionRegistryPostProcessor.getOrder();
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
sayenBeanDefinitionRegistryPostProcessor.postProcessBeanFactory(beanFactory);
}
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
sayenBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry(beanFactory);
}
@Bean
public AutowiredBean autowiredBean() {
return new AutowiredBean();
}
@Bean
@Transform(type = MegaSuperKarim.class)
public Karim Karim() {
return new Karim();
}
@Bean
@Transform(type = SuperGuillaume.class)
public Guillaume Guillaume() {
return new Guillaume();
}
@Bean
public Yoann Yoann() {
return new Yoann();
}
@Bean
public Nicolas Nicolas() {
return new Nicolas();
}
@Bean
public BeanHolder beanHolder() {
return new BeanHolder();
}
}
public class TransformFactoryBean implements FactoryBean<Object> {
@Autowired
private AutowiredBean pouet;
private Class<?> objectType;
boolean singleton = true;
@Override
public Object getObject() throws Exception {
return objectType.getConstructor().newInstance();
}
@Override
public Class<?> getObjectType() {
return objectType;
}
@Override
public boolean isSingleton() {
return singleton;
}
public void setObjectType(Class<?> objectType) {
this.objectType = objectType;
}
public AutowiredBean getPouet() {
return pouet;
}
public void setSingleton(boolean singleton) {
this.singleton = singleton;
}
}
public class SayenBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {
private static Logger logger = LoggerFactory.getLogger(MainConfiguration.class);
@Override
public int getOrder() {
return 0;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
logger.debug("rien");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {
//DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) beanFactory;
for (String originalBeanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition originalBeanDefinition = beanFactory.getBeanDefinition(originalBeanName);
logger.debug("original beanName=" + originalBeanName + ", " + originalBeanDefinition.toString());
if (originalBeanDefinition.isAbstract()) {
continue;
}
Transform sayenAnnotation = getMethodAnnotation(beanFactory, originalBeanDefinition);
/*if (sayenAnnotation == null) {
Class<?> originalBeanClass = beanFactory.getType(originalBeanName);
sayenAnnotation = AnnotationUtils.findAnnotation(originalBeanClass, Transform.class);
*/if (sayenAnnotation == null) {
continue;
}/*
}*/
Class<? extends Sayan> sayenClass = sayenAnnotation.type();
RootBeanDefinition sayenFactoryBeanDefinition = new RootBeanDefinition(TransformFactoryBean.class, 3/*Autowire.BY_TYPE.value()*/, true);
sayenFactoryBeanDefinition.getPropertyValues().add("objectType", sayenClass);
sayenFactoryBeanDefinition.getPropertyValues().add("singleton", true);
String factoryBeanName = originalBeanName;
logger.debug("remove beanName=" + originalBeanName + ", " + originalBeanDefinition.toString());
beanFactory.removeBeanDefinition(originalBeanName);
logger.debug("register beanName=" + factoryBeanName + ", " + sayenFactoryBeanDefinition.toString());
beanFactory.registerBeanDefinition(factoryBeanName, sayenFactoryBeanDefinition);
}
}
private Transform getMethodAnnotation(BeanDefinitionRegistry beanFactory, BeanDefinition originalBeanDefinition) {
String originalBeanFactoryBeanName = originalBeanDefinition.getFactoryBeanName();
String originalBeanFactoryMethodName = originalBeanDefinition.getFactoryMethodName();
if (originalBeanFactoryBeanName == null || originalBeanFactoryMethodName == null) {
return null;
}
Class<?> originalBeanFactoryBeanClass = ClassUtils.getUserClass(((DefaultListableBeanFactory)beanFactory).getType(originalBeanFactoryBeanName));
try {
Method method = originalBeanFactoryBeanClass.getMethod(originalBeanFactoryMethodName);
return AnnotationUtils.getAnnotation(method, Transform.class);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
【问题讨论】: