记录一个在使用@Aspect注解方式实现Spring MVC + Spring + jdbcTemplate读写分离的过程遇到的一个问题 。(基于spring的aop来实现)
问题:定义在controller层的切点无效。
原因:Spring的父子容器。
自定义注解:
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceChange {
boolean slave() default false;
}
切面类:
@Aspect
public class DataSourceAspect {
@Pointcut("@annotation(com.yuan.gx.util.DataSourceChange)")
public void changeDS() {
}
@Before("changeDS()")
public void performance() {
System.out.println("Spring AOP");
}
}
aop配置:
<!-- 启用CGliB -->
<aop:aspectj-autoproxy/>
<!--切面注入spring自定义标签-->
<bean id="dsChangeAspect" class="com.yuan.gx.util.DataSourceAspect"/>
该注解在service层或其他地方都能正常使用,当是在controller层时就无效。
经过各大论坛,各路技术大神的帮助,终于找到了问题的原因。
我是将aop配置在了spring-context.xml 核心配置文件中,该配置文件会被ContextLoaderListenerclass加在,Spring会创建一个WebApplicationContext上下文,称为父上下文(父容器) ,保存在 ServletContext中,keyWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。
而spring-mvc.xml是DispatcherServlet,可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),子上下文可以访问父上下文中的内容,但父上下文不能访问子上下文中的内容。 它也保存在 ServletContext中,key是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称
当spring加在父容器的时候就会去找切入点,但是这个时候切入的controller是在子容器中的,父容器是无法访问子容器,所以就拦截不到。
如果将上述的配置文件放到spring-mvc.xml中,那么问题就解决了。
网友评论