Spring DI - do not initialize all dependent beans

I have a ServiceA that has a dependency on ServiceB. Service B comes from a spring bean file with lazy-init = true ie, I want serviceB to be initialized when and if I ask for that bean.

However, I use ServiceA throughout my application, and when we do initialization based on the ServiceB injection, we set the setter.

I want ServiceA not to initialize ServiceB until any method in ServiceA that needs ServiceB is called. One way to do this is to use Aspects , but I was considering the simplest solution for this, especially in the spring xml file for serviceB or some annotation in serviceB or any proxy server.

Can anyone help?

+6
source share
4 answers

I think LazyInitTargetSource doing what you need.

Useful when a proxy link is required for initialization, but the actual target should not be initialized before first use . When the target bean is defined in the ApplicationContext (or BeanFactory, which eagerly creates a single-line singleton beans), it should also be marked as "lazy-init", otherwise it will be created by the ApplicationContext (or BeanFactory) instance at startup.

+6
source

Another approach you can try is discussed at http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/aop/framework/autoproxy/target/LazyInitTargetSourceCreator.html :

[LazyInitTargetSourceCreator is] A TargetSourceCreator that provides a LazyInitTargetSource for each bean which is defined as lazy-init. This will lead to the creation of a proxy server created for each of these beans, allowing you to get a link to such a bean without actually initializing the target bean instance.

To register as a custom TargetSourceCreator for the autoproxy creator in combination with custom interceptors for specific beans or to create only lazy-init proxies. For example, since an autodetectable bean framework in the context of an XML application definition:

  <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="customTargetSourceCreators"> <list> <bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator"/> </list> </property> </bean> <bean id="myLazyInitBean" class="mypackage.MyBeanClass" lazy-init="true"> ... </bean> 

If you find yourself doing this several times in the context of the application, this will save on configuration.

+1
source

I do not know about Spring, but in Guice you would use Provider<ServiceB> , so when you were ready to use this service, you would go to provider.get().callMethodOnB(...) .

This, I believe, is part of the JSR-330 specification, so it has an equivalent thing in Spring (I have not used the latest version of Spring for some time).

0
source

You can also use the injection method . As a rule, you need to get a new instance of a singleton bean from the context, but it can also be used in your case.

Example:

 package org.test.lazy; public abstract class ParentBean { public abstract LazyBean getLazy(); public void lazyDoingSomething() { getLazy().doSomething(); } } 

 package org.test.lazy; public class LazyBean { public void init() { System.out.println("Initialized"); } public void doSomething() { System.out.println("Doing something"); } } 

 package org.test.lazy; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class LazyTest { @Autowired private ParentBean parentBean; @Test public void test() { parentBean.lazyDoingSomething(); parentBean.lazyDoingSomething(); } } 

 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd "> <import resource="classpath:org/test/lazy/Lazy-context.xml"/> <bean id="parentBean" class="org.test.lazy.ParentBean"> <lookup-method bean="lazyBean" name="getLazy"/> </bean> </beans> 

 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd " default-lazy-init="true"> <bean id="lazyBean" class="org.test.lazy.LazyBean" init-method="init" /> </beans> 

Thus, a lazy bean will be initialized only once upon request.

0
source

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


All Articles