论坛首页 Java企业应用论坛

遇到一个设计上的问题,请问如何解决?

浏览 16640 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (2)
作者 正文
   发表时间:2008-06-19  
循环引用了

<bean id="teacherManager" class="test.teacherManagerImpl">   
</bean>  
 
<bean id="app" class="test.appImpl">  
<property name="teacherManager" ref="teacherManager" />  
<property name="studentManager" ref="studentManager" />  
</bean> 

0 请登录后投票
   发表时间:2008-06-19  
rocwon 写道
fly_ever 写道
引用
如果teacherManager需要studentManager的方法,就会在teacherManager添加一个studentManager

就说明这个方法不能放到studentManager里面。


正解~
Manager, Service一类的东西,通常作为一个Facade或者integration script对外暴露服务接口的,应该互相没有依赖的关系。如果出现这种情况,就要回头考虑下设计是否有问题。


Manager调用Manager,在实际中很常见啊,好像没什么好法子来避免。
0 请登录后投票
   发表时间:2008-06-19  
确实是设计的问题,依赖环是设计的大忌,需要消除依赖环
0 请登录后投票
   发表时间:2008-06-19  
volking 写道
谢谢各位。看了becoder的帖子,我又改了一遍。解决了,虽然不完美,先凑活用吧。

一开始我全部用构造函数注入,难后改成属性注入,不知道什么原因,没有改干净,改来改去全糊涂。
现在确定,属性注入是支持的。

如果能全部用构造函数注入就好了,我是看了roller的源码才有这个想法,他是用的google guice。

用这种方法的好处就是,不用在业务层定义一大堆其他业务类的变量,只要一个就可以很方便的调用任何一个业务类。

这2天把代码优化了一下,把dao和manager(业务类)结合了,删掉了dao,分开写实在太累人。



看你的意思是你的代码有dao、manager、service三层啊,呵呵,整合是对的,用了hibernate没必要有dao这一层。

再教你一些偷懒的办法,web层只能调用service,事务只加在service这一层,manager可以不加事务,manager也可以不用接口,因为你可以只对service做回归测试。
0 请登录后投票
   发表时间:2008-06-19  
1.循环引用应该尽量避免,但也不得不说,最初的时候我也遇到设计上这种循环引用的问题,后面直接很干脆的改动(其实应该是改进了设计),这样比较根治,而且不失设计的缺陷

2.spring支持属性值的循环引用注入(是不是觉得和第一点说得有点冲突?)其实问题出现在你对这些循环引用的业务类进行自动代理事务(不信你可以把事务配置先除去试试)!
所以becoder兄弟说的“如果通过Setter方式的依赖注入,Spring是支持Circular dependencies的,刚刚也做了简单的测试,在Spring2.5下启动和使用都没有问题

楼主能否贴一下详细的错误? ”估计就是因为你当时可能没加入自动事务管理:)
0 请登录后投票
   发表时间:2008-06-20  
<bean id="beanServiceLocator" class="com.ctitc.framework.core.ServiceLocator">
		<property name="objects">
			<map>
				<entry
					key="com.ctitc.framework.auth.service.CompanyTypeService">
					<ref bean="beanCompanyTypeService" />
				</entry>

				<entry
					key="com.ctitc.framework.auth.service.DepartmentService">
					<ref bean="beanDepartmentService" />
				</entry>
			</map>
		</property>
</bean>




<bean name="/DepartmentEditController.do" class="com.ctitc.framework.auth.controller.DepartmentEditController">
		<property name="serviceLocator">
			<ref bean="beanServiceLocator" />
		</property>
</bean>


我是在controller中注入serviceLocator ,如果需要的话,也可以在service层注入这个属性,这样,就可以在某个service中使用其他的service实例了。

DataTransService service = (DataTransService) getServiceLocator().locate(DataTransService.class.getName());


0 请登录后投票
   发表时间:2008-06-20  
icewubin 写道
volking 写道
谢谢各位。看了becoder的帖子,我又改了一遍。解决了,虽然不完美,先凑活用吧。

一开始我全部用构造函数注入,难后改成属性注入,不知道什么原因,没有改干净,改来改去全糊涂。
现在确定,属性注入是支持的。

如果能全部用构造函数注入就好了,我是看了roller的源码才有这个想法,他是用的google guice。

用这种方法的好处就是,不用在业务层定义一大堆其他业务类的变量,只要一个就可以很方便的调用任何一个业务类。

这2天把代码优化了一下,把dao和manager(业务类)结合了,删掉了dao,分开写实在太累人。



看你的意思是你的代码有dao、manager、service三层啊,呵呵,整合是对的,用了hibernate没必要有dao这一层。

再教你一些偷懒的办法,web层只能调用service,事务只加在service这一层,manager可以不加事务,manager也可以不用接口,因为你可以只对service做回归测试。


我开始用的是:dao,manager(也就是service,事务也是这层),现在把dao和manager合并。一个通用的dao足够了。直接注入到manager里面。

刚刚看了一篇文章:注释驱动的IoC。感觉用处不大,xml不是有default-autowire了吗?
0 请登录后投票
   发表时间:2008-06-20  
不要指定property注入,而是通过autowire,应该可以。。

我就是这样做的。
0 请登录后投票
   发表时间:2008-06-20  
我在这里来个泛泛而谈吧。为了便于说明,service用S表示,各种Manager用M1,M2...表示。 -> 表示以来关系。
现在楼主的问题可以表示为:
1) S->M1, S->M2 ...
2) M1->S, M2->S ...
3) Mi->Mj, ...

这样就构成了一个循环依赖,移植性很差,以后改动很不方便。
问题的核心是Mi->Mj. M1,M2, ...其实是处在同一层,他们应该是没有任何依赖。如果存在依赖,那就说明设计有问题。那么我可以从分解Mj入手,Mj分解为MP1,MP2,MP3..., 让Mi依赖更小粒度的MPj。所以现在来看依赖关系变为:
1)Mi->MPj
2)Mj->MP1,MP2,...
当然MP1,MP2,...可以表示其他符号,例如OP1,OP2...。
这样,循环依赖解除。
这种方法其实就是把被依赖的模块分解为更细的粒度,让更细的粒度被依赖。
细粒度,重用性高。

0 请登录后投票
   发表时间:2008-06-20  
yujianqiu 写道
volking 写道
举个例子来说:例如有n多个业务类接口及其实现:teacherManager,studentManager.....
我以前这样用,如果teacherManager需要studentManager的方法,就会在teacherManager添加一个studentManager。然后注入:
<bean id="teacherManager" class="test.teacherManagerImpl">
<property name="studentManager" ref="studentManager" />
</bean>

现在我想用一个类来统一管理这些业务类。
<bean id="teacherManager" class="test.teacherManagerImpl">
<property name="app" ref="app" />
</bean>

<bean id="app" class="test.appImpl">
<property name="teacherManager" ref="teacherManager" />
<property name="studentManager" ref="studentManager" />
</bean>

但是在启动tomcat的时候,报错。原因是在初始化teacherManagerImpl时,需要初始化app,
而初始化app,需要初始化teacherManagerImpl。就像进入死循环一样。

请问appImpl应该如何初始化那些业务类呢?好像用spring的注入无法实现。


第一,循环依赖应该避免
第二,个人觉得“用一个类来统一管理这些业务类”毫无意义,因为这是Spring的工作


完全同意~
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics