团结源码阐明 Spring 容器与 SpringMVC 容器之间的干系
问题
问题描写:项目中发明,自界说切面注解在 Controller 层正常事情,在 Service 层却无法正常事情。为了便于阐明,去掉代码中的业务逻辑,只留下场景。
/** * Description: 自界说打印时间的注解 * Created by jiangwang3 on 2018/5/9. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented public @interface PrintTime { }
/** *Description:打印时间注解的理会器 * @author jiangwang * @date 11:28 2018/5/14 */ @Aspect public class PrintTimeProcessor { private Logger LOGGER = LoggerFactory.getLogger(getClass()); @Pointcut("@annotation(com.foo.service.annotation.PrintTime)") public void printTimePoint() { } @Around("printTimePoint()") public Object process(ProceedingJoinPoint jp) throws Throwable{ System.out.println(); LOGGER.error("开始运行措施。。。Start==>"); Object proceed = jp.proceed(); LOGGER.error("竣事啦,运行竣事==>"); System.out.println(); return proceed; } }
/** * @author jiangwang * @date 2018/5/14 */ @RestController @RequestMapping(value = "/user") public class UserController { private Logger logger = LoggerFactory.getLogger(getClass()); @Resource private UserService userService; @RequestMapping(value = "/serviceAspect", method={RequestMethod.GET}) public String serviceAspect(){ return userService.serviceAspect(); } @RequestMapping(value = "/controllerAspect", method={RequestMethod.GET}) @PrintTime public String name(){ logger.info("Controller层----测试切面"); return "controllerAspect"; } }
/** * @author jiangwang * @date 11:34 2018/5/14 */ @Service public class UserService { private Logger logger = LoggerFactory.getLogger(getClass()) @PrintTime public String serviceAspect(){ logger.info("Service层---测试切面"); return "serviceAspect"; } }
<context:annotation-config /> <!-- 动态署理开启 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <context:component-scan base-package="com.foo" > <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 民众设置引入 --> <import resource="classpath:spring/spring-config-dao.xml" />
<mvc:annotation-driven /> <mvc:default-servlet-handler /> <!-- 动态署理开启 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <!-- mvc controller --> <context:component-scan base-package="com.foo.web.controller" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan> <bean class="com.foo.service.processor.PrintTimeProcessor"/>
以上为主要代码。项目运行之后,发此刻 Service 层的注解切面未生效,而在 Controller 层正常。而当我将 springmvc.xml 中的
<bean class="com.foo.service.processor.PrintTimeProcessor"/>
迁移至 spring.xml 中,发明 Service 层与 Controller 层的注解切面均可正常运行。WHY???
从源码的角度探究该问题
由于源码中的要领较长,所以只贴出重点且与主题相关的代码。发起团结当地源码一起看。
Web 项目标进口是 web.xml,所以咱们从它开始。
<!-- Spring Config --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-config.xml</param-value> </context-param> <!-- SpringMvc Config --> <servlet> <servlet-name>springMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>