How to create an object that needs a dynamic parameter

I always have a question from the first day I used spring. If a class has a constructor that needs two parameters, but these 2 parameters are not fixed, they are generated according to the input request, each time they are different, but I need a spring container to control the class instance, how to do it in spring ? for instance

Class A{ A(int x,int y){//omit} } 

but x and y are not fixed, we need to calculate x and y by our program, then we can create an instance for A in regular java code, for example below

  int x=calculate(request); int y=calculate(request); A a=new A(x,y); 

But how to make spring control the instantiation of class A?

More info: Why do I need a spring-driven class A because A depends on some other classes that spring manages.

+4
source share
6 answers
  • The easiest way to do this is to use ApplicationContext.getBean(String name, Object... args) - it can create a prototype -scoped bean by passing the given arguments to its constructor. Obviosly is not recommended to use ApplicationContext directly in any bean that uses A

  • A more elegant approach is to hide the creation of A behind the factory. This factory can use the previous approach internally or it can get a bean in normal mode ( Provider<A> etc.), and then call the non- public initialization method to pass these parameters (instead, pass parameters using the constructor).

  • Another approach is to use @Configurable and load time in time , which allows Spring to initialize objects created with new . Although this requires additional configuration of the runtime.

+7
source

they are generated according to the input request, every time they are different from each other, but I need a spring container to control the class instance, how to do it in spring?

No. Classes that must be created in response to user input are not designed to be managed with Spring.

Just because you use spring to manage some beans does not mean that all beans / classes should be managed using Spring.

+2
source

You want your Spring Bean to be defined as prototype instead of singleton . This way, with every new request, your Spring context will create a new bean instance.

In the Java configuration, it will look something like this:

@Scope("prototype") @Bean public MyBean myBean() { ... }

In xml:

<bean id="myBean" class="whatever.MyBean" scope="prototype"> ...

There are also areas that can be tied to HTTP sessions. Cm:

http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html

And, as others have pointed out, you will need to define a factory method for your bean:

See: Spring and pass parameters to the factory method at runtime

+1
source

Perhaps you need to change the constructor to:

 Class A{ A(Request request){ this.x=calculate(request); ....} } 
0
source

I would suggest that int is replaced with some instance of Object . One way to achieve this is to use Spring FactoryBean to configure the initialization of your bean:

 class AFactory implements osbfFactoryBean { private SomeObject firstParam; private OtherObject secondParam; public Object getObject() { return new A(firstParam, secondParam); } public Class getObjectType() { return A.class; } public boolean isSingleton() { return false; // ie every time #getObject() is called a new instance is created === prototype scope } public void setFirstParam(SomeObject firstParam){} public void setSecondParam(OtherObject secondParam){} } 

Note that if SomeObject and OtherObject can actually be other FactorBean , which are factories for A dependencies, then every time AFactory#getObject() is called, you really get a new instance of A that uses fresh instances of the dependencies it needs.

0
source

You can try using this method in the BeanFactory class (extended ApplicationContext)

Object getBean (String name, Object ... args) throws a BeansException;

in your case: context.getBean ("A", x, y);

where "A" is the bean name for class A.

0
source

Source: https://habr.com/ru/post/1433397/


All Articles