views:

272

answers:

3

I load additional singleton beans definitions at runtime from external jar file into existing XmlWebApplicationContext of my application:


BeanFactory beanFactory = xmlWebApplicationContext.getBeanFactory();
DefaultListableBeanFactory defaultFactory = (DefaultListableBeanFactory)beanFactory;
final URL url = new URL("external.jar");
final URL[] urls = {url};
ClassLoader loader = new URLClassLoader(urls, this.getClass().getClassLoader());
defaultFactory.setBeanClassLoader(loader);
final ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(defaultFactory);
final DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
resourceLoader.setClassLoader(loader);
scanner.setResourceLoader(resourceLoader);
scanner.scan("com.*");
Object bean = xmlWebApplicationContext.getBean("externalBean");


After all above xmlWebApplicationContext contains all external definitions of beans. But when i am trying to get bean from context exception is thrown:

Couldn't generate CGLIB proxy for class ...

I saw in debug mode that in the bean initialization process first time proxy is generated by org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator

and than it is tried to generate proxy with org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator

but fails with mentioned exception.

A: 

Make sure the bean:

  • isn't final
  • has a non-private constructor
Bozho
Not final and has public constructor.Strange but it works if bean initialized not in run time, but in the strarting of main context regular process with all other beans.It works also if bean definition is added in PostProcessor method just before main context started.I've tried to refresh context, but after refresh loaded additional bean definitions are dissapeared.
VasylV
refresh recreates all beans and this is not the best solution for me, my goal is to load bean definition at runtime without restarting of all main spring web context
VasylV
Give the class (edit your question)
Bozho
A: 

Cause was determined. Second proxy creator definition was founded in spring-common-manager.xml:

"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
which intercepts beans with names DAO, Dao, *ManagerTarget.

During my external bean creation, proxy bean classLoader was set to system class loader. So proxy creator couldn't find class definition for external bean.

It seems that without refresh class loader, which added to default factory is invisible for some utility beans such proxy creators.

My Solution is to obtain proxy creator bean and to set implicitly class loader to it, but maybe some better way exists to resolve this problem.

VasylV
A: 

Ok, nderstanding comes during process. More appropriate way to load external bean definitions without refreshing of main application context is to use child application context for external module with it's own class loader and configurations.

VasylV