aspectj-autoproxy Controller未生效解决方案

 本周做业务需求,需要对api的响应时间做监控。第一想法是在需要监控的api里面答应日志,记录care的信息,这样的最大问题就是不容易扩展,需要在每个api里面添加几乎相同的代码。当时,Java的通用做法是切片,利用Java语言提供的反射能力,结合spring 的三大特性之一的aop(面向切面编程)思想,可以完全解耦的添加切片就行,这样在低耦合、高内聚的编程原则下是显得比较优雅,但是难免要牺牲一下效率,反射是对象运行时动态特性,需要消耗额外的性能。想到之前没有独立在工程里引入切片,同时保持代码的优雅,决定是切片。

步骤

1、业务切片代码  


@Aspect
@Component
public class ApiAspect {


@Around("execution (* com.jinxu.api..*.*(..))")
public Object apiLog(ProceedingJoinPoint joinPoint) throws Throwable {
Long startTime = 0l;
Long endTime = 0l;
Object result = null;
try {
startTime = System.currentTimeMillis();
result = joinPoint.proceed();
endTime=System.currentTimeMillis();
} catch (Exception e) {
throw e;
} finally {
try {
Object[] args = joinPoint.getArgs();
Object object = args[0];
if (object instanceof HttpServletRequest) {
object = ((HttpServletRequest) object).getParameterMap();
}
String method = joinPoint.getSignature().getName();
String request = JsonUtils.json(object);//此处注意json与非json的对应关系
String response = JsonUtils.json(result);//
logger.debug(String.format("method:%s" + " - request:%s" + " - response:%s" + " - cost:%s", method, request, response, endTime - startTime));
} catch (Exception e) {
logger.error("com.jinxu.api包切片异常,但是不影响正常业务:" + e);
}
}
return result;
}
}
 需要引入的jar包如下:

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
</dependency>
  其中cglib是运行期扩展Java类与实现Java接口的代码,也就是jdk反射的扩展,一般用它替换jdk自带的更可用。
2、配置spring加载文件

<!-- AOP -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
  其中可以加载代码中有@Aspect标签的切片,proxy-target-class属性值决定是接口的还是类的代理被创建。如果proxy-target-class 属性值被设置为true,那么类的代理将起作用,如cglib库;如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK基于接口的代理。当时,如果没有对应接口,只有实现,类的代理将起作用。

3、问题

  关于切片的使用,其他工程和网上的资料确实比较多,于是直接配置了。结果发现但是实际Controller切片并未生效,aop切片没有被执行到。一般情况下,模仿其他配置,放在applicationContext.xml里面,是会起作用的,于是查了很多资料,对比其他工程,没有实质收获。

  The aspects and the beans to be applied needs to be in the same ApplicationContext but ApplicationContext is not aware of

 WebApplicationContext . 
  Indeed your controller (annotated by @Controller) and your aspects (annotated by @Aspect) should be in the same Spring context. 

  Usually people define their controllers in the dispatch-servlet.xml or xxx-servlet.xml and their service beans (including the aspects) in the

 main applicationContext.xml. It will not work. 

  When Spring initializes the MVC context, it will create a proxy for your controller but if your aspects are not in the same context, Spring will not create interceptors for them. 

  翻译过来就是Controller是定义在xxx-servlet.xml配置文件中,所以定义在applicationContext.xml中的aspects切片并不会生效,需要将aspects定义转移到xxx-servlet.xml文件中。修改过来问题就解决了,大家如果遇到可以参考上面简陋的解决步骤。
————————————————
版权声明:本文为CSDN博主「晓风残月xj」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xj2419174554/java/article/details/52626974

猜你喜欢

转载自www.cnblogs.com/sidesky/p/12717832.html