How to search and auto-register all beans under a specific package - spring

I have x number of beans under some base-package say com.mypackage.basepackage.
What I am trying to do is to auto-scan this package and register all the beans to ApplicationContext with BeanDefinitionRegistryPostProcessor.
Here is how I am trying to do this.
public class BeanRegistrar implements BeanDefinitionRegistryPostProcessor
{
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
}
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException
{
//loop n-number of times and register all the scanned beans.
BeanDefinition beanDefinition = new RootBeanDefinition(scannedbeans.class, Autowire.BY_TYPE.value(), true);
registry.registerBeanDefinition("beanName", beanDefinition);
}
}
What I want is to loop on com.mypackage.basepackage , look for beans and register them.
I know I can scan basepackage with
<context:component-scan base-package="com.mypackage.basepackage" />

use ClassPathBeanDefinitionScanner
http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.html

Related

Spring: Is it possible to lazy load all Spring Beans without #Lazy

I am looking to lazy load all spring beans when running integration tests that utilize #ContextConfiguration. Ideally I would be able to apply this lazy loading in one place and have it applied to any beans that are loaded via the #ContextConfiguration annotation.
Yes it is.
You can do this using BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor.
#Configuration
static class LazyBeans implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry bdr) throws BeansException {
for (String name : bdr.getBeanDefinitionNames()) {
final BeanDefinition beanDefinition = bdr.getBeanDefinition(name);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
beanDefinition.setLazyInit(true);
}
}
}
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory clbf) throws BeansException {}
}

Access spring component from servlet

I have a controller (for example. MyManager) where I invoke method (for example myMethod() ) of component class (bean), for example MyComponent. I have I servlet where I want to invoke myMethod() . In servlet I have annotated MyManager by #Autowired annotation , despite this I got NullPointerException. I saw this kind of topic but it is not useful for me. For imagination I write little code :
public class myClass extends HttpServlet {
#Autowired
private MyComponent component;
public void init(ServletConfig config) throws ServletException{
super.init(config);
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
protected void doGet(HttpServletRequest req,HttpServletResponse res) throws ... {
List<MyObject> objects =component.myMethod(); // Here is the problem, component is null
}
}
}
I make Spring configuration file "context.xml" and I got bean (component) object, but now I have problem with injected EntityManager in bean object. Now it is null , can anyone help me to solve this problem ? Also update init() method.
public void init(ServletConfig config) throws ServletException{
ApplicationContext con = new ClassPathXmlApplicationContext("context.xml");
component = (MyComponent) con.getBean("myBean");
}
You cannot autowire dependencies like that because Servlets are not Spring Beans. You need to do something like the following:
#Override
public void init() throws ServletException {
super.init();
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
component= applicationContext.getBean(MyComponent.class);
}
Also drop the #Autowired annotation from component

Spring proxy beans from Interface

What is the correct way to create proxy beans by interfaces?
public class JdbiRepositoryAnnotationBeanPostProcessorTest {
private DBI dbi = mock(DBI.class);
#org.junit.Test
public void testIncompleteBeanDefinition() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(JdbiRepositoryAnnotationBeanPostProcessor.class);
ctx.register(MyConfig.class);
ctx.refresh();
ITest bean = ctx.getBean(ITest.class);
assertNotNull(bean);
}
#JdbiRepository
public static interface ITest {
}
#Configuration
#ComponentScan(basePackageClasses = {ITest.class},
includeFilters = {#ComponentScan.Filter(type = FilterType.ANNOTATION, value = JdbiRepository.class)})
public static class MyConfig {
}
}
I have tried bean post processor but It did not help me.
Edit:
I wanted to use component scanning by including annotation filter but it did not help me too.
Edit:
I want to create instances by another library which is creating proxy beans as this:
TestInterface proxy = factory.onDemand(TestInterface.class);
Edit:
I have extended InstantiationAwareBeanPostProcessorAdapter for JdbiRepositoryAnnotationBeanPostProcessor.
I have been just logging currently. But I can not see my interfaces as a bean.
Please note that I have also changed my test code above.
public class JdbiRepositoryAnnotationBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if(!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException("AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory");
}
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
// this.dbiMap = this.beanFactory.getBeansOfType(DBI.class);
}
}
The problem was related to ComponentScanning not PostBeanProcessor. ComponentScan is scanning only concrete classes that is why my processor did not work. I had to create a custom importer for interfaces.

How can I programatically add a beanPostProcessor to a ClassPathXmlApplicationContext?

There's a way to programatically add a beanPostProcessor to a ClassPathXmlApplicationContext ?
I can do it declaratively in the xml, but apparently there's no way to add programatically.
My processor must do something like if my bean is a MyInterfaceAware, then do setMyInterface(...).
I need to do it in code cause MyInterface implementation is instantiated in code, it's not available when starting the XML.
I'm using Spring 3.1.2.RELEASE.
Thanks,
... this is what I'm doing ...
public void setSpringBeanFactory(BeanFactory beanFactory) {
this.beanFactory = (ApplicationContext) beanFactory;
((ClassPathXmlApplicationContext) beanFactory).getBeanFactory().addBeanPostProcessor(new BeanPostProcessor() {
public Object postProcessBeforeInitialization(Object bean,
String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean,
String beanName) throws BeansException {
if (bean instanceof RegistryAware)
((RegistryAware) bean).setRegistry(ApplicationContextRegistryImpl.this);
return bean;
}
});
((ClassPathXmlApplicationContext)beanFactory).refresh();
}
Try with context.getBeanFactory().addBeanPostProcessor(beanPostProcessor)
Edit
You could use a BeanFactoryPostProcessor also:
public class RegistryBeanPostprocessorConfigurer implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.addBeanPostProcessor(getRegistryBeanPostProcessor());
}
}
context.addBeanFactoryPostProcessor(new RegistryBeanPostProcessorConfigurer());
context.refresh();

How can I get the bean definitions without actually creating the beans?

For static analysis of my Spring config, I need just the bean definitions - actually creating the beans would cause problems because some need a (properly initialized) database.
Is there a way to prevent the AnnotationConfigApplicationContext to create any beans? Instead, it should just load and analyze the config and stop.
you could implement the BeanDefinitionRegistryPostProcessor interface. in the postProcessBeanDefinitionRegistry method you have access to BeanDefinition's
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// ...
}
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.getBeanDefinition("myBean");
}
}

Resources