Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiating spring beans in dynamically created classes

Tags:

java

spring

I am dynamically creating classes which contain spring beans, however the beans are not getting instantiated or initialised, leaving them as null.

How do I make sure that a dynamically created class creates all of its spring beans properly?

This is how I am dynamically creating the class:

Class ctransform;
try {
    ctransform = Class.forName(strClassName);
    Method handleRequestMethod = findHandleRequestMethod(ctransform);
    if (handleRequestMethod != null) {
        return (Message<?>) handleRequestMethod.invoke(ctransform.newInstance(), message);
            }
    }

This leaves all spring bean objects within ctransform (of type strClassName) as null.

like image 840
Xetius Avatar asked Dec 29 '22 16:12

Xetius


1 Answers

Whenever you instantiate classes, they are not spring-managed. Spring has to instantiate classes so that it can inject their dependencies. This with the exception of the case when you use @Configurable and <context:load-time-weaver/>, but this is more of a hack and I'd suggest against it.

Instead:

  • make the bean of scope prototype
  • obtain the ApplicationContext (in a web-app this is done via WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext))
  • if the classes are not registered (and I assume they are not), try casting to StaticApplicationContext (I'm not sure this will work), and call registerPrototype(..) to register your classes in the context. If this doesn't work, use GenericContext and its registerBeanDefinition(..)
  • get all the instances that match your type, using appContext.getBeansOfType(yourclass); or if you just registered it and know its name - use just appContext.getBean(name)
  • decide which one is applicable. Usually you will have only one entry in the Map, so use it.

But I would generally avoid reflection on spring beans - there should be another way to achieve the goal.


Update: I just thought of an easier solution, that will work if you don't need to register the beans - i.e. that your dynamically generated classes won't be injected in any other dynamically generated class:

// using WebApplicationContextUtils, for example
ApplicationContext appContext = getApplicationContext(); 
Object dynamicBeanInstance = createDyamicBeanInstance(); // your method here
appContext.getAutowireCapableBeanFactory().autowireBean(dynamicBeanInsatnce);

And you will have your dependencies set, without having your new class registered as a bean.

like image 199
Bozho Avatar answered Dec 31 '22 06:12

Bozho