最近突然想到一个问题
以前在用struts2(注解)+spring
struts的action拖给spring管了(spring的bean在Ioc容器范围内默认都是singlen的),但是没有加@scope("prototype")却从来没有出现过线程安全问题。
而一年前还在学校时做ssh2(没用注解)练习时,不在bean后加prototype都会出现线程安全问题,当时所有的action后都加了scope=prototype。
难道注解和不用注解,struts2创建action的方式不一样?
于是做了个测试
- public
class TestAction extends BaseAction { -
@Autowired -
private UserService userService; -
@Action("test") -
public String test() throws Exception { -
System.out.println("action HashCode:"+this.hashCode()); -
userService.getUserName(); -
return "success"; -
} - }
- @Service
- public
class UserService { -
public void getUserName(){ -
System.out.println("service HashCode:"+hashCode()); } - }
- action
HashCode:9928297 - service
HashCode:32262619 - action
HashCode:13620718 - service
HashCode:32262619 - action
HashCode:19792917 - service
HashCode:32262619
而每次的service是同一个也就是单例的
(难道action并没有交个spring托管)
又把以前在学校做的老项目(纯xml)拿来 把以前的scope="prototype"去掉
发现action确实是单例的
所以struts2(注解) 在和spring集成时action默认是new的,不用注解spring扫描action的话也是用的new。
而非注解时如果把action加入bean的话默认是单例的。
所以如果大家struts2是用注解的话就不需要在action上加@scope("prototype")了;
当指定struts.objectFactory为spring时,struts2框架就会把bean转发给spring来创建,装配,注入。但是bean创建完成之后,还是由struts容器来管理其生命周期。配置方式:
(1)struts.xml中:
- <</span>constant
name="struts.objectFactory" value="spring" />
(2)struts.properties中:
- struts.objectFactory=spring
通常情况下,这样子就够了,然后在struts的action-mapping配置文件中,如下:
- <</span>action
name="user" class="com.myapp.admin.web.action.user.UserAction"></</span>action>
即可,如果在Action中有依赖于其它的BEAN,也会被自动注入进来。这时候,Action实例是以prototype方式创建的,SPRING会为每个请求创建一个ACTION的实例。
在某些时候,你可能希望不仅仅让SPRING创建和装配Action对象,还希望让SPRING完全管理这些对象,如希望使用AOP或者希望使用acegi时。这时候,只需要在spring的配置文件中定义这些action 即可。如在applicationContext.xml文件中:
- <</span>bean
id="user" class="com.myapp.web.action.user.UserAction"/>
然后在action-mapping中,指定class="user"即可。