How to create a bean by type in Spring?

旧巷老猫 提交于 2019-12-24 08:19:08

问题


In my ApplicationContext I have several Beans being created the same style. So I have a lot of dublicated code writing a FactoryBean for each of this beans. Those beans have a common ground, implementing all one special interface.

I would like to move all that bean creation to one factory. That one would have to provide a methode like this

<T extends CommonInterface> T createInstance(Class<T> clazz);

There I could implement all the instantiation necessary to create one of my special beans.

My implementation would be called by spring for

@Autowired
private MyCommonInterfaceImplementation impl;

in that way

createInstance(MyCommonInterfaceImplementation.class)

So far I looked at BeanFactory and FactoryBean, both seem not to be I'm searching for.

Any suggestions?


回答1:


why not use @bean

@Bean
public MyCommonInterfaceImplementation getMyCommonInterfaceImplementation(){
    return MyBeanFactory.createInstance(MyCommonInterfaceImplementation.class);
}

//should autowire here
@Autowired
private MyCommonInterfaceImplementation impl;



回答2:


Basically you need the @Bean annotation on a "factory" only if you need some special handling during the creation of a bean.

If everything can be @Autowired, either by setters, fields, or one constructor, and nothing else needs to be done on a bean during initialization, you can simply declare the annotation @Component on each implementation of your interface. This works as long as you have component scanning active inside your application. The result will be that for each component spring will create a bean which you can use.

I'm writing this on a mobile so showing code is not the best. Just follow some tutorial on @ComponentScan, or if you need, let me know and I can augment this answer with an example.




回答3:


As of Spring 4.3 you no longer have to annotate your bean classes and you can let them be instantiated via a componentscan.

@Configuration @ComponentScan( value = "some.package.path", includeFilters = { @Filter(type = ASSIGNABLE_TYPE, value = { MyClass1.class, MyClass2.class, MyClass3.class }) })

This actually creates beans for the three classes listed there. The example should work without filters as well (everything in the package becomes a bean). This works as long as the classes have a single constructor that can be used for autowiring. I don't think it is possible to filter for all implementations of a particular interface and then register a bean.

To do that, you might do something with a ContextListener and e.g. use reflection to find out what classes to instantiate and then use context.autowire(..) to inject any dependencies from your context. A bit hacky but it might work.

@Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext context = event.getApplicationContext(); MyClass bean = context .getAutowireCapableBeanFactory() .autowire(MyClass.class, Autowire.BY_NAME.value(), true); ... }

That still leaves the problem of how to get the bean registered in the context of course.

You might also be able to adapt the answer to this SO question on how to add beans programmatically.




回答4:


Finally the best approach I've found is using a ConfigurationClassPostProcessor. As example I've used https://github.com/rinoto/spring-auto-mock

But, since it is quite complicated and "too much magic" to create beans from nothing, we decided to explicitly create those beans via @Bean.

Thanks for your answers.



来源:https://stackoverflow.com/questions/39348010/how-to-create-a-bean-by-type-in-spring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!