AOP介绍
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是Spring框架中的一个重要内容,它通过对既有程序定义一个切入点,然后在其前后切入不同的执行内容,比如常见的有:打开数据库连接/关闭数据库连接、打开事务/关闭事务、记录日志等。基于AOP不会破坏原来程序逻辑,因此它可以很好的对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
pom配置
<dependencies>
<dependency>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter
</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter-logging
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter-test
</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba
</groupId>
<artifactId>fastjson
</artifactId>
<version>1.2.68
</version>
</dependency>
<dependency>
<groupId>org.apache.commons
</groupId>
<artifactId>commons-lang3
</artifactId>
<version>3.9
</version>
</dependency>
<dependency>
<groupId>org.projectlombok
</groupId>
<artifactId>lombok
</artifactId>
<version>1.18.12
</version>
</dependency>
<dependency>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter-log4j
</artifactId>
<version>1.3.8.RELEASE
</version>
</dependency>
<dependency>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter-freemarker
</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot
</groupId>
<artifactId>spring-boot-starter-aop
</artifactId>
</dependency>
</dependencies>
log4j.properties配置文件
# LOG4J配置
log4j.rootCategory=INFO, stdout, file, errorfile
log4j.category.com.didispace=DEBUG, didifile
log4j.logger.error=errorfile
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
# root日志输出
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.file=logs/all.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
# error日志输出
log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorfile.file=logs/error.log
log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd
log4j.appender.errorfile.Threshold = ERROR
log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout
log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
# com.didispace下的日志输出
log4j.appender.didifile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.didifile.file=logs/my.log
log4j.appender.didifile.DatePattern='.'yyyy-MM-dd
log4j.appender.didifile.layout=org.apache.log4j.PatternLayout
log4j.appender.didifile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n
设置AOP
package com
.yiyang
.myfirstspringdemo
.aspect
;
import org
.aspectj
.lang
.JoinPoint
;
import org
.aspectj
.lang
.annotation
.AfterReturning
;
import org
.aspectj
.lang
.annotation
.Aspect
;
import org
.aspectj
.lang
.annotation
.Before
;
import org
.aspectj
.lang
.annotation
.Pointcut
;
import org
.slf4j
.Logger
;
import org
.slf4j
.LoggerFactory
;
import org
.springframework
.stereotype
.Component
;
import org
.springframework
.web
.context
.request
.RequestContextHolder
;
import org
.springframework
.web
.context
.request
.ServletRequestAttributes
;
import javax
.servlet
.http
.HttpServletRequest
;
import java
.util
.Enumeration
;
@Aspect
@Component
public class LogAspect {
private static final Logger logger
= LoggerFactory
.getLogger(LogAspect
.class);
@Pointcut("execution(public * com.yiyang.myfirstspringdemo.controller.*.*(..))")
public void webLog() {
}
@Before("webLog()")
public void doBefore(JoinPoint joinPoint
) throws Throwable
{
ServletRequestAttributes attributes
= (ServletRequestAttributes
) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request
= attributes
.getRequest();
logger
.info("URL : " + request
.getRequestURL().toString());
logger
.info("HTTP_METHOD : " + request
.getMethod());
logger
.info("IP : " + request
.getRemoteAddr());
Enumeration
<String> enu
= request
.getParameterNames();
while (enu
.hasMoreElements()) {
String name
= (String
) enu
.nextElement();
logger
.info("name:{},value:{}", name
, request
.getParameter(name
));
}
}
@AfterReturning(returning
= "ret", pointcut
= "webLog()")
public void doAfterReturning(Object ret
) throws Throwable
{
logger
.info("RESPONSE : " + ret
);
}
}
package com
.yiyang
.myfirstspringdemo
.controller
;
import org
.springframework
.web
.bind
.annotation
.GetMapping
;
import org
.springframework
.web
.bind
.annotation
.RestController
;
@RestController
public class HelloController {
@GetMapping("/hello")
public String
hello() {
return "hello world";
}
}
启动类
package com
.yiyang
.myfirstspringdemo
;
import org
.springframework
.boot
.SpringApplication
;
import org
.springframework
.boot
.autoconfigure
.SpringBootApplication
;
@SpringBootApplication(scanBasePackages
= {"com.yiyang.myfirstspringdemo"})
public class MyFirstSpringDemoApplication {
public static void main(String
[] args
) {
SpringApplication
.run(MyFirstSpringDemoApplication
.class, args
);
}
}
验证
浏览器中输入:http://localhost:8080/hello 查看控制台的日志输出:
2020-10-03 15:04:17,999 INFO LogAspect:38 - URL : http://localhost:8080/hello
2020-10-03 15:04:18,007 INFO LogAspect:39 - HTTP_METHOD : GET
2020-10-03 15:04:18,008 INFO LogAspect:40 - IP : 0:0:0:0:0:0:0:1
2020-10-03 15:04:18,011 INFO LogAspect:51 - RESPONSE : hello world