昨天(2019-04-09),我们一组开发的一哥们,发现 AOP 在执行权限认证的时候,是不执行的,没有执行 AOP 切面配置的内容。我把之前执行的测试 aop 项目(测试AOP的项目)发了过去,发现按照步骤操作了,但是还是不能够执行的问题。
一、顺序执行的问题。
WEB 项目的启动顺序
※※ 简述服务器启动时Webapp的web.xml中配置的加载顺序
加载顺序是:ServletContext -> context-param -> listener -> filter -> servlet。
- 启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点。
- 接着,容器创建一个ServletContext(servlet上下文),这个web项目的所有部分都将共享这个上下文。
Spring是listener ,因此其配置文件会先于Spring mvc的servlet加载。
- 执行Spring配置文件后,Spring会创建一个WebApplicationContext上下文,称为父上下文(父容器)。
- spring mvc可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器)。
上面的顺序总结为:
- 【web.xml】–>【applicationContent-*.xml】–>【springmvc.xml】
- 【ServletContext】–>【WebApplicationContext】–>【DispatcherServlet】
- 【web 容器】–>【Spring 容器 (父容器)】–>【SpringMVC 容器(子容器)】
二、说说我的那个测试项目
- 测试AOP的项目
- 看代码说话。
- application.xml 配置文件中的详细内容。两种方式,注意注解的位置。
- 我们看到的是注解非常的方便。正如下图所示:
三、Spring AOP使用@Aspect无法作用于Controller层
原因:父容器中的aop:aspectj-autoproxy/不能作用到子容器才扫描的Controller。
四、其他问题。
- Spring AOP 的 JDK动态代理、cglib的代理。
默认的:
<aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/>
属性1:proxy-target-class。 true 是cglib 代理、false 是 JDK 动态代理。
属性2:expose-proxy。 是否暴露当前代理对象为ThreadLocal模式。
### Spring Aop 默认的是 JDK 动态代理。针对 Service 接口。
<aop:aspectj-autoproxy proxy-target-class="false">
### Spring Aop 使用 cglib 代理。针对 Controller 、ServiceImpl (一般使用接口)类。
<aop:aspectj-autoproxy proxy-target-class="true">
- Spring 和 SpringMVC 加载文件的内容设置。
建议:Spring MVC 和 Spring 整合的时候,SpringMVC 的 dispatcher-servlet.xml 文件中配置扫描包,不要包含 service的注解,Spring的applicationContext.xml文件中配置扫描包时,不要包含controller的注解。
配置如下内容:
### application.xml 文件。
<context:component-scan base-package="com.web">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
### springmvc.xml 文件。
<context:component-scan base-package="com.service">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.service" />
</context:component-scan>
- 因为 springmvc.xml 与 applicationContext.xml 不是同时加载的,如果不进行这样的设置,那么,spring 就会将所有带 @Service 注解的类都扫描到容器中,等到加载applicationContext.xml 的时候,会因为容器已经存在 Service 类,使得cglib将不对Service进行代理,直接导致的结果就是在applicationContext 中的事务配置不起作用,发生异常时,出现无法对数据进行回滚的情况。