springmvc中使用aop有时候不成功。这是因为spring启动的时候初始化了一个applicationContext,而DispatcherServlet也会生成一个WebApplicationContext。切面和被拦截的beans需要在同一个applicationContext中,aop才能起作用。知道了原因,那就很容易解决了。
1、切面和被拦截类统一放到applicationContext里,由applicationContext初始化(或使用注解扫描),事务拦截可以这样做。一般情况下,事务在service层控制,不影响使用dispatcherservlet处理controller。但这样如果想在这里配置aop拦截controller层将会失效。
2、切面和被拦截类统一放到*servlet.xml中配置,由dispatcherservlet的WebApplicationContext初始化。这样controller和其他类都可以被拦截到。这样的话,如果存在多个dispatcherservlet公用service层,会出现问题。原因如下:
applicationContext是根。打个比方,applicationContext相当于父类,WebApplicationContext相当于子类。WebApplicationContext可以引用applicationContext已经初始化的bean。要搞清楚这种关系,把需要优先初始化的类交由applicationContext初始化。
开发中,我们习惯使用自动扫描@Controller、@Service @Repository、@Component这些注解。这里就会涉及到配置自动扫描的包的问题。
一般我们在spring的application.xml中,让其不要扫描 @Controller的注解(对于springmvc来说),因为这个一般交由dispatcherservlet来处理。而在springmvc的配置文件中(一般为*servlet.xml)只需要扫描@Controller ,相应的配置例子如下:
spring的配置文件application.xml:
<context:component-scan base-package="com.dcfs">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
配置其不扫描@Controller注解。
springmvc的配置文件如下:
<!-- scan the package and the sub package -->
<context:component-scan base-package="com.dcfs"
use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.RestController" />
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
注意设置
use-default-filters="false"
设置不适用默认过滤器(默认情况下,默认过滤器是使用的)。
下面是component-scan说明:
Scans the classpath for annotated components that will be auto-registered as Spring beans. By
default, the Spring-provided @Component, @Repository, @Service, and @Controller stereotypes will
be detected. Note: This tag implies the effects of the 'annotation-config' tag, activating @Required,
@Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit
annotations in the component classes, which is usually desired for autodetected components (without
external configuration). Turn off the 'annotation-config' attribute to deactivate this default behavior,
for example in order to use custom BeanPostProcessor definitions for handling those annotations.
Note: You may use placeholders in package paths, but only resolved against system properties
(analogous to resource paths). A component scan results in new bean definition being registered;
Spring's PropertyPlaceholderConfigurer will apply to those bean definitions just like to regular bean
definitions, but it won't apply to the component scan settings themselves.