Actually I encountered the same problem in my projects:
When having multiple service beans which contain references to each other, and these service beans are proxied (for transaction management for example), this problem always appear, no matter in which order the beans are declared, and no matter if you use lazy-init for (some of) them.
(And of course I am proxying interfaces, not the service implementation class)
To give you an example:
Code:
<bean id="myService1Target" class="my.company.service.impl.MyService1Impl">
<property name="myService2" ref="myService2"/>
</bean>
<bean id="myService1" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="documentManagementServiceTarget"/>
<property name="proxyTargetClass" value="false"/>
<property name="proxyInterfaces">
<list>
<value>my.company.service.interfaces.MyService1</value>
</list>
</property>
<property name="interceptorNames">
<value>transactionInterceptor</value>
</property>
</bean>
<bean id="myService2Target" class="my.company.service.impl.MyService2Impl">
<property name="myService1" ref="myService1"/>
<property name="myService3" ref="myService3"/>
</bean>
<bean id="myService2" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="documentManagementServiceTarget"/>
<property name="proxyTargetClass" value="false"/>
<property name="proxyInterfaces">
<list>
<value>my.company.service.interfaces.MyService2</value>
</list>
</property>
<property name="interceptorNames">
<value>transactionInterceptor</value>
</property>
</bean>
<bean id="myService3Target" class="my.company.service.impl.MyService3Impl">
<property name="myService1" ref="myService1"/>
<property name="myService2" ref="myService2"/>
</bean>
<bean id="myService3" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="documentManagementServiceTarget"/>
<property name="proxyTargetClass" value="false"/>
<property name="proxyInterfaces">
<list>
<value>my.company.service.interfaces.MyService3</value>
</list>
</property>
<property name="interceptorNames">
<value>transactionInterceptor</value>
</property>
</bean>
The solution is to declare a "third-party" lazy bean that contains references to the actual service interfaces (some kind of "services repository"), and set it to lazy-init="true".
And then change all the other service implementations to access the other services only through this services repository bean, not directly.
In the given example this will become:
Code:
<bean id="myService1Target" class="my.company.service.impl.MyService1Impl">
<property name="myServicesRepository" ref="myServicesRepository"/>
</bean>
<bean id="myService1" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="documentManagementServiceTarget"/>
<property name="proxyTargetClass" value="false"/>
<property name="proxyInterfaces">
<list>
<value>my.company.service.interfaces.MyService1</value>
</list>
</property>
<property name="interceptorNames">
<value>transactionInterceptor</value>
</property>
</bean>
<bean id="myService2Target" class="my.company.service.impl.MyService2Impl">
<property name="myServicesRepository" ref="myServicesRepository"/>
</bean>
<bean id="myService2" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="documentManagementServiceTarget"/>
<property name="proxyTargetClass" value="false"/>
<property name="proxyInterfaces">
<list>
<value>my.company.service.interfaces.MyService2</value>
</list>
</property>
<property name="interceptorNames">
<value>transactionInterceptor</value>
</property>
</bean>
<bean id="myService3Target" class="my.company.service.impl.MyService3Impl">
<property name="myServicesRepository" ref="myServicesRepository"/>
</bean>
<bean id="myService3" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="documentManagementServiceTarget"/>
<property name="proxyTargetClass" value="false"/>
<property name="proxyInterfaces">
<list>
<value>my.company.service.interfaces.MyService3</value>
</list>
</property>
<property name="interceptorNames">
<value>transactionInterceptor</value>
</property>
</bean>
<bean id="myServicesRepository" class="my.company.service.impl.MyServicesRepository" lazy-init="true">
<property name="myService1" ref="myService1"/>
<property name="myService2" ref="myService2"/>
<property name="myService3" ref="myService3"/>
</bean>
Unfortunately this kinda defeats the whole idea of automatic wiring of beans, because now you will have to manually declare all the wiring of beans...
And also, by creating this type of "services repository" you will get to tight-coupling of beans, instead of loose-coupling...
Maybe a more elegant solution would be to identify groups of related services (maybe based on the packages or modules), and create multiple "service repositories": documentManagementServicesRepository, usersManagementServicesRepository, etc.
(Of course I am speaking of complex applications, with tens of packages and hundreds of service interfaces/classes)
Note that the same problem (and solution) applies even if you are using the newer style of declarative transaction management:
Code:
<aop:config>
<aop:pointcut id="myService1Operation" expression="execution(* my.company.service.interfaces.MyService1.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="myService1Operation"/>
</aop:config>