How to get Factory + AOP running in Spring

I have a singleton Spring bean (and it should remain a single) that needs a new instance of another bean (Lets call it X) every time a method is executed.

So far I have been considering the following approaches:

  • just create X using the new one. This worked for a while, but now we need the Spring AOP functions for X, so it no longer works, since the resulting instances are not managed by Spring.

  • I considered FactoryBean as a dependency, but I would only get one X instance from FactoryBean that does not match my first instance.

  • the current plan is to manually search for X in the Spring context and declare it there using a prototype. This should work, but I think it is really ugly.

=> How can I insert a factory into my bean so that I can call its factory method at any time convenient for me and get a managed instance of Spring from it.

+4
source share
2 answers

A picker for a scenario like this is called a search method search method . In short, this takes the approach of calling the bean method, resulting in a new instance of the bean being created. You should start by creating a class with an abstract method that will eventually provide an instance of the dependencies:

abstract class MyClient implements Client { void businessMethod(…) { Dependency dependency = getDependencyInstance(); … } abstract Dependency getDependencyInstance(); } 

Now you go over and configure the bean prototype definition for the dependency:

 <bean id="dependency" class="….DependencyImpl" scope="prototype" /> 

Like a client using the lookup-method element to always get a fresh instance of the dependency for each method call:

 <bean class="….MyClient"> <lookup-method name="getDependencyInstance" bean="dependency" /> </bean> 

This will lead to the creation of a CGLib proxy server for MyClient , and the declaration of the getDependencyInstance(…) method will be supported by TargetSource with a reference to BeanFactory and the name of the bean for the search. Each time the method is called, the bean search will be called and a new instance of the configured bean prototype will be returned.

+12
source

I do not see a problem with the factory bean, and I would do it like this:

 import org.springframework.beans.factory.FactoryBean; import org.springframework.stereotype.Component; @Component public class X { public static class XFactory implements FactoryBean<X> { @Override public X getObject() throws Exception { return new X(); } @Override public Class<?> getObjectType() { return X.class; } @Override public boolean isSingleton() { return false; } } } 

and enter this factory bean.

Otherwise, you can host your X bean with

 @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS, value=ConfigurableBeanFactory.SCOPE_PROTOTYPE) 

You must use the default proxy mode so that spring creates a proxy server that always returns a new instance to your singleton.

If you are using XML configuration than this:

 <bean id="x" class="X" scope="prototype"> <aop:scoped-proxy> </bean> 

Good luck.

Edit:

When you comment your factory via @Component (I added it above), return false to #isSingleton and make sure you don't return your X twice, you can enter the factory bean with @ Got it in your singleton.

Otherwise, I just checked

 import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.stereotype.Component; @Component @Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS) public class X { } 

works as expected.

Edit 2:

If you don’t want to enter a factory bean but just want to add a dependency, you can prototype the area of ​​your factory (@Scope (proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")) but a new factory is created every time X is involved, which, probably not what you want.

If you do not want to enter factory yourself, I would go with the Olivers search method.

+2
source

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


All Articles