I have the following components
Scenario
My library has a class that needs to register itself as a bean in to the web application context, without telling the users of the library to change their code (xml, spring context, or classes).
So, in other words, I have a Class, and a spring context, I want from only my class to register on this spring context without changing anything in it. So is there any time spring will scan the classpath for classes implementing a certain interface, if so what interface?
What I've tried
Using BeanFactoryPostProcessor but this requires me to access the application context and call addBeanFactoryPostProcessor as far as I can find.
Using ApplicationContextInitializer but this forces me to change the web.xml
A bunch of other things like different Aware interfaces but I have not found anything yet that allows my class to self-register to the Bean Factory and be picked up in the spring context, I want to be able to use things like the Scheduled annotation. And I always want others in the spring context to be able to find my class by Autowired annotation.
Examples
Class that I own and inside my library
package spring.outside
public class ClassA {
@Scheduled(fixedDelay=5000)
public void doSomething() {
}
}
Class that the user of my library owns
package spring.inside
public class ClassB {
@Autowired
private ClassA classA;
}
With a spring file containing something like this, that I do not own
<context:component-scan base-package="spring.inside"/>
If this is not possible I would like to explore the possibilities of what I can do in my class that is inside spring to, as easily as possible, tell the spring context to pick it up.
Examples
package spring.outside
public class ClassA {
@Scheduled(fixedDelay=5000)
public void doSomething() {
}
}
Class that the user of my library owns
package spring.inside
public class ClassB {
@Autowired
private ClassA classA;
}
Another class that is meant to initiate the ClassA and put it into the spring application context, I just show the code of some of the different things I've tested in it now since I don't know how it should look like.
package spring.inside
public class ClassC implements BeanFactoryPostProcessor, ApplicationContextInitializer, BeanFactoryAware, ApplicationContextAware {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerSingleton("classA", new ClassA());
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.addBeanFactoryPostProcessor(this);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
((ConfigurableListableBeanFactory)beanFactory).registerSingleton("classA", new ClassA());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
((ConfigurableApplicationContext)applicationContext.getParentBeanFactory()).addBeanFactoryPostProcessor(this);
((ConfigurableListableBeanFactory)applicationContext.getParentBeanFactory()).registerSingleton("classA", new ClassA());
}
}
Tried
But all of these seem to work partially, but it always ends up getting some timing error such as: ClassA needs input variables in the constructor that is Autowired inside ClassC, some of these are set when ClassC creates ClassA. Another scenario I saw was ClassB not being able to Autowired ClassA because that was done before. So what would be the correct and nice way of doing this?
I'm running spring version 3.2.11.RELEASE
If anyone knows how to solve this problem in a nice way and not something that feels like "ugly hack" I would be very happy to know!
Thanks and best regards!
In this case you must include ClassA
as a spring bean in the Spring Context XML
<bean id="classA" class="spring.inside.ClassA">
or using a Configuration class
package spring.inside;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import spring.outside.ClassA;
@Configuration
public class AppConfiguration {
@Bean
ClassA classA() {
return new ClassA();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.