我可以直接在类上使用@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。
我不确定这样做是否会破坏任何弹簧原则,或者这是否是常规事情。
我的初衷是有效的。 但是我现在有另一个问题。 我无法使用我想要的类型自动装配来自我想要的工厂的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);
}
}
答案 0 :(得分:1)
如果@CustomAnnotation的唯一目的是影响类/ bean的创建方式,那么你采取了正确的方法。在这种情况下,注释的范围应该是在创建时(在@Configuration MyConfiguration中将其移动到的位置)而不是类范围(@Target(ElementType.TYPE))。 你有效地说@CustomAnnotation在创建后没有进一步用于MyBean,你的框架永远不会再需要检查MyBean这个注释。这也意味着@CustomAnnotation可能用于创建其他bean(MyBean2等)。