一, 背景
目前部门有一个培训,需要讲一下Spring的使用,看到有同学提出问题,想自定义实现一个打日志的注解,下面就记录一下实现过程。
环境:
Spring 6.1.5, 不使用Spring Boot.
二,实现步骤
1, 引入Spring和Spring AOP相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
2,在springmvc-servlet.xml里添加配置(这里的springmvc-servlet.xml是在web.xml中指定的servlet标签里名称决定的)。
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
3,新建一个注解
java
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyLog {
}
4,新增一个切面
java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyLogAspect {
@Pointcut("@annotation(com.xxx.xxx.config.MyLog)")
public void dsPointCut() {
}
@Before("dsPointCut()")
public void doBefore() throws Throwable {
System.out.println("我从before到注解的切点了");
}
@After("dsPointCut()")
public void doAfter() {
System.out.println("我从after退出了");
}
@Around("dsPointCut()")
public Object doAround(ProceedingJoinPoint point) throws Throwable {
System.out.println("我从around到注解的切点了");
Object result = point.proceed();
System.out.println("我从around退出了");
return result;
}
}
这里需要注意一点: point.proceed();表示程序继续运行, 然后拿到Object result, 一定要返回,不然被切面命中的方法会没有返回值, 也就是around这个处理要有返回值(因为它这个方法是自己定义,可以设置成void)。
5, 使用注解
java
import com.xxx.xxx.config.MyLog;
import com.xxx.xxx.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(value="/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value="/list", method= RequestMethod.GET)
@MyLog
public String getUser(@RequestParam(value="name") String name) {
System.out.println(userService.getName());
List<String> nameList = userService.getUserNames();
nameList.stream().forEach(a -> System.out.println(a));
return "hahaha";
}
}
6, 运行项目,调用接口,可以看到打印出想要的日志
三,总结
具体原理网络上一大堆,但是没有看到有人用Spring去实现,其他人实现的基本上都是用了SpringBoot,没有参考意义。
希望对你有帮助!