背景:
貌似很久之前就看到过关于spring在servlet中配置component-scan的写法:
<context:component-scan base-package="org.mm.xiao" >
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
当时也没怎么注意,就看网上人家说是servlet里面要这样配置然后在application-context里面要这样配置:
<context:component-scan base-package="org.mm.xiao" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
目的是为了让spring的事物不至于失效,网上百度了下说是什么要controller先扫描注入,此时还没事物增强的。
但我怎么也没想通,今日自己来试验了下,发现,貌似不是他们讲的那样。于是在此记录下,希望各路大神指点一二。
实践:
其实我感觉就是application-context和servlet内的bean加载顺序问题,于是我就写了一个service接口,其实现类如下:
package org.mm.xiao.serviceImpl;
import org.mm.xiao.Vo.User;
import org.mm.xiao.service.UserService;
public class UserServiceImpl implements UserService {
private String name;
@Override
public User getUser() {
User user = new User();
user.setAge(20);
if(null!=this.name){
user.setName(this.name);
}else{
user.setName("xiaoQ");
}
return user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
然后在application-context.xml中配置了下这个bean
<bean id="userService" class="org.mm.xiao.serviceImpl.UserServiceImpl"/>
同时我也在servlet.xml中配置了一下这个bean
<beans:bean id="userService" class="org.mm.xiao.serviceImpl.UserServiceImpl">
<beans:property name="name" value="hello"/>
</beans:bean>
然后在controller里面调了下service的方法
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@Autowired
UserService service ;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, ModelMap model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
System.err.println(service.getUser());
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
启动服务器后访问http://localhost:8080/xiao/
结果如下:
User [name=hello, age=20]
相信不用过多的来讲,大家也都明白了,原来是spring先加载application-context中的bean然后再加载servlet中的bean,于是servlet中的bean就覆盖了application-context中的bean了,结果就是大家看到的。
上面的问题答案也就出来了,如果在servlet中扫描所有的bean,那么在application-context中对spring事物的aop代理就会被覆盖,所以可能事物就不起作用了。我个人还是觉得最好把bean用xml的形式来声明。以后大家一起开发比较容易维护,不然都是注解真的很难搞代码,虽然写的比较high。