基于自定义注解的springAOP配置

基于自定义注解的springAOP配置

SpringMVC项目需要做一下登陆日志操作日志,愚蠢的我居然最先想到的在Controller基类中添加一个方法大家来调用,转而一想日志操作不就是AOP的典型应用场景么,随即一边google一边踩坑填坑,终于是完成了第一次的SpringAOP配置.

自定义注解annotation类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package iie.df.analysis.misc;

import java.lang.annotation.*;

/**
* 操作日志AOP注解
* @author cheyantao
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActionMethod {
String modal() default "";
String method() default "";
}

AOP切面类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package iie.df.analysis.misc;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Component
@Aspect
public class AopLogging {
private static final Logger LOG = LoggerFactory.getLogger(AopLogging.class);

@Pointcut(value = "@annotation(actionMethod)",argNames = "actionMethod")
public void actionMethodPointCut(ActionMethod actionMethod){

}
@Around(value = "actionMethodPointCut(actionMethod)")
public Object afterActionMethod(ProceedingJoinPoint point,ActionMethod actionMethod) throws Throwable {
System.out.println("执行目标方法之前,模拟开始事务...");
Object obj=point.proceed();
System.out.println(actionMethod.modal()+"--"+actionMethod.method());
return obj;//记得返回
}
}

应用类

1
2
3
4
5
6
7
@RequestMapping(value = "/post-signin", method = RequestMethod.POST)
@ActionMethod(modal = "登录日志",method = "用户登录")
public ModelAndView signinPostDispatch(...)
throws UnsupportedEncodingException {
...
return new ModelAndView("redirect:/");
}

spring配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<description>Page Dispatch Config</description>
<!--不相关的配置都删掉了,主要是下面两个 以及bean schema中的aop和context支持.-->
<context:component-scan base-package="iie.df.analysis"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

这里有一个坑,平常我们都会把spring的相关配置在application-context.xml中配置,但是在springMVC项目中把这些配置放到application-context中的时候可能会出现无法进如切面方法情况,我就比较倒霉碰见了.具体解决方案是把以上的配置放到了dispatcher-servlet.xml配置文件中,多谢大神无私的回答:八楼大神造福大家.
如果你也遇到了这种问题,项目中又找不到dispatcher-servlet.xml这个文件,你应该可以再web.xml中找到相关的配置文件

1
2
3
4
5
6
7
8
9
10
<servlet>
<servlet-name>Analysis</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--藏在这里-->
<param-value>classpath*:config/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

几处坑

  1. 上文springMVC配置的坑.
  2. aop切面两个依赖类确实,附上他们的maven地址,如果maven更新失败,请自行下载jar包maven install

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- https://mvnrepository.com/artifact/cglib/cglib -->
    <dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
    </dependency>
    <dependency>
    <groupId>asm</groupId>
    <artifactId>asm</artifactId>
    <version>3.3.1</version>
    </dependency>

    3.切面类的注解问题.
    开始参照网上一些例子,大部分没有将注解作为参数传进@Around方法中,造成了获取注解属性必须通过发射获取,代码显得非常臃肿和丑陋.所以大概可以参照一下我的切面类的相关注解.另外这里爬坑的关键文章是stackoverflow专治疑难杂症,另外挖一个坑日后填整理一下AOP相关注解的知识
    4.切面类的@around方法记得把ProceedingJoinPoint执行后的结果返回.

    其他几个用得到的连接

其他

大约耗费了我一晚上的时间来搞定这个问题,虽然磕磕绊绊,最后总算是把这个东西配置出来了.最近确确实实感受到了自己两年工作经验跟一年工作经验时候的差别,一年前面对这些繁琐的配置问题大概就是无从下口,找公司的同事帮忙了.如今回过头来看看不知道什么时候自己也就习惯了这些配置问题了,并且能共一点点借助google把问题解决.突然想起大学那个在实验室呆了一个大学,写了无数文档,就是徘徊在编程门口入不了门的少年了.可惜如今已经奔三,不过庆幸的是,还好,总算可以独当一面了.