如果你需要使用lombok.jar这个软件包简化对象代码定义,
关于在CentOS8系统上如何安装lombok.jar到STS开发工具里,请参考下面唯一一张图片的说明:
AOP 可以实现在不修改源代码的情况下给程序动态统一添加功能,而不需要破坏某个操作业务模块代码的完整性
范例1:
package com.contoso;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.contoso;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/")
public class FooController {
@Autowired
FooService foo;
@GetMapping(path = "foo")
public String print() {
return foo.saying("hello spingboot aop");
}
}
package com.contoso;
import org.springframework.stereotype.Service;
@Service
public class FooService {
public String saying(String content) {
return "saying:"+content;
}
}
package com.contoso;
import org.springframework.stereotype.Component;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Component
@Aspect
public class FooAspect {
public FooAspect() {
System.out.println("创建FooAspect成功");
}
// 定义切点
@Pointcut("execution(* *.saying(..))")
public void say() {
}
//环绕通知。
@Around("say()")
public void sayAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知开始");
pjp.proceed();// 执行方法
System.out.println("环绕通知结束");
}
@Before("say()")
public void sayBeFore(JoinPoint joinPoint) {
System.out.println("sayBeFore");
System.out.println("获取连接点方法运行时的入参列表:" + joinPoint.getArgs());
System.out.println("获取连接点的方法签名对象:" + joinPoint.getSignature());
System.out.println("获取连接点所在的目标对象:" + joinPoint.getTarget());
}
@After("say()")
public void sayAfter(JoinPoint joinPoint) {
System.out.println("sayAfter");
}
}
启动 spring-boot-app 控制台会打印如下信息:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.1.RELEASE)
2019-11-18 11:23:16.152 INFO 5664 --- [ main] com.contoso.Application : Starting Application on contoso.com with PID 5664 (/home/myth/coding/spring-boot-aop-example/target/classes started by myth in /home/myth/coding/spring-boot-aop-example)
2019-11-18 11:23:16.155 INFO 5664 --- [ main] com.contoso.Application : No active profile set, falling back to default profiles: default
2019-11-18 11:23:16.751 INFO 5664 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2019-11-18 11:23:16.764 INFO 5664 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 7ms. Found 0 repository interfaces.
2019-11-18 11:23:17.028 INFO 5664 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-11-18 11:23:17.403 INFO 5664 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-11-18 11:23:17.415 INFO 5664 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-11-18 11:23:17.415 INFO 5664 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.27]
2019-11-18 11:23:17.504 INFO 5664 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-11-18 11:23:17.504 INFO 5664 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1238 ms
创建FooAspect成功
2019-11-18 11:23:18.295 INFO 5664 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-11-18 11:23:18.618 INFO 5664 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-11-18 11:23:18.620 INFO 5664 --- [ main] com.contoso.Application : Started Application in 2.902 seconds (JVM running for 3.518)
调用api接口控制台会打印如下信息:
环绕通知开始
sayBeFore
获取连接点方法运行时的入参列表:[Ljava.lang.Object;@4edb39e5
获取连接点的方法签名对象:String com.contoso.FooService.saying(String)
获取连接点所在的目标对象:com.contoso.FooService@39b46e28
环绕通知结束
sayAfter
范例1执行后,如果你有留意的话 ,控制器返回的是空值null,而不是我们期望的内容saying:hello spingboot aop
原因是pjp.processed()执行后结果没有返回,所以sayAround(ProceedingJoinPoint pjp)方法不能没有返回值
正确的代码如下:
package com.contoso;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
@Component
@Aspect
public class FooAspect {
public FooAspect() {
System.out.println("创建FooAspect成功");
}
// 定义切点
@Pointcut("execution(* *.saying(..))")
public void say() {
}
//环绕通知。
@Around("say()")
public Object sayAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知开始");
Object object = pjp.proceed();// 执行方法
//printArgs(pjp);
System.out.println("环绕通知结束");
return object;//必须要有返回值,controller控制器才会有正确内容返回,否则控制器只会返回null值。
}
@Before("say()")
public void sayBeFore(JoinPoint joinPoint) {
System.out.println("sayBeFore");
System.out.println("获取连接点方法运行时的入参列表:" + joinPoint.getArgs());
System.out.println("获取连接点的方法签名对象:" + joinPoint.getSignature());
System.out.println("获取连接点所在的目标对象:" + joinPoint.getTarget());
}
@After("say()")
public void sayAfter(JoinPoint joinPoint) {
System.out.println("sayAfter");
}
public void printArgs(ProceedingJoinPoint point) throws Exception {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
// TODO:获取请求参数
Object[] args = point.getArgs();
System.err.println(args[0]);
}
}
范例2:
第1步:创建数据库表以及插入测试用户数据
CREATE DATABASE `testdb`;
USE `testdb`;
CREATE TABLE `sys_log` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) DEFAULT NULL COMMENT '用户名',
`operation` VARCHAR(50) DEFAULT NULL COMMENT '用户操作',
`method` VARCHAR(200) DEFAULT NULL COMMENT '请求方法',
`params` VARCHAR(5000) DEFAULT NULL COMMENT '请求参数',
`time` BIGINT(20) NOT NULL COMMENT '执行时长(毫秒)',
`ip` VARCHAR(64) DEFAULT NULL COMMENT 'IP地址',
`create_date` DATETIME DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='系统日志';
CREATE TABLE `sys_user` (
`id` INT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) DEFAULT NULL,
`code` VARCHAR(10) DEFAULT NULL,
`email` VARCHAR(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `sys_user` VALUES ('2', 'jack', '10012', 'test1@136.com');
INSERT INTO `sys_user` VALUES ('3', 'cathy', '10078', 'test2@136.com');
INSERT INTO `sys_user` VALUES ('4', 'mark', '10633', 'test3@136.com');
我们使用开发工具STS 进行开发(spring-tool-suite-3.9.10)
第2步:创建Spring Starter Project项目
第3步:安装Mybatis逆向工程插件
第4步:配置依赖包
在pom.xml文件中手动增加3个依赖包(joda-time、aspectjweaver、mybatis-generator-core):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.contoso</groupId>
<artifactId>spring-boot-aop-example2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-aop-example2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- SpringBoot - MyBatis 逆向工程 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
第5步:创建Mybatis插件逆向工程时需要的配置文件,此文件不是自动生成的,
创建空文件src/main/resources/mybatis-generator.xml,并且手动配置其内容,
这个文件可以保存一份在自己的电脑上,以后逆向工程时,稍微改一下就能直接使用啦
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="application.yml" />
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=UTC" userId="root" password="dbpass">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<javaModelGenerator targetPackage="com.contoso.domain" targetProject="spring-boot-aop-example2/src/main/java">
<property name="enableSubPackages" value="false"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<sqlMapGenerator targetPackage="mappers" targetProject="spring-boot-aop-example2/src/main/resources">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.contoso.dao" targetProject="spring-boot-aop-example2/src/main/java">
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
<table tableName="sys_log" domainObjectName="SysLog"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false">
</table>
<table tableName="sys_user" domainObjectName="SysUser"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false">
</table>
</context>
</generatorConfiguration>
第6步:修改资源文件application.properties的扩展名改为application.yml,并且手动配置其内容:
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/testdb?useSSL=false
username: root
password: dbpass
mybatis:
mapper-locations: classpath*:/mappers/*.xml
请特别注意mapper-locations的参数值的写法,参数值里面的mappers就是targetPackage的值mappers,
mappers其实是个文件夹,application.yml中的mappers-locations可千万别写错了,否则就没法逆向工程了
<sqlMapGenerator targetPackage="mappers" targetProject="spring-boot-aop-example2/src/main/resources">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
第7步:上面的pom.xml文件早已配置好,现在使用maven install 安装依赖包,
准备为下一步开始进行逆向工程而做准备
第8步:使用Mybatis插件开始逆向工程,生成我们需要的代码和mapper文件(xml格式的)
第9步:创建以下截图中出现的软件包以及类文件
package com.contoso.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
//value将用于存储 "具体的操作模块的操作描述"
String value() default "";
}
package com.contoso.aspect;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.contoso.annotation.LogAnnotation;
import com.contoso.dao.SysLogMapper;
import com.contoso.domain.SysLog;
import com.fasterxml.jackson.databind.ObjectMapper;
@Aspect
@Component
public class LogAspect {
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
@Autowired
private SysLogMapper sysLogMapper;
@Autowired
private ObjectMapper objectMapper;
// 定义切点:发生的时机 - 即一旦加了这个注解,将触发某些事情
@Pointcut("@annotation(com.contoso.annotation.LogAnnotation)")
public void logPointCut() {
}
//定义通知:环绕通知 - 执行核心任务之前 + 执行完核心任务之后 该做的事情
@Around("logPointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
// TODO:执行核心任务
Object object = joinPoint.proceed();
long time = System.currentTimeMillis() - start;
saveLog(joinPoint, time);
return object;
}
// TODO:保存操作日志
private void saveLog(ProceedingJoinPoint point, Long time) throws Exception {
log.info("开始触发-保存操作日志");
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
SysLog entity = new SysLog();
// TODO:获取请求操作的描述信息
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
if (annotation != null) {
entity.setOperation(annotation.value());
}
// TODO:获取操作方法名
String className = point.getTarget().getClass().getName();
String methodName = signature.getName();
entity.setMethod(className + "." + methodName + "()");
// TODO:获取请求参数
Object[] args = point.getArgs();
entity.setParams(objectMapper.writeValueAsString(args[0]));
// TODO:获取剩余参数
entity.setTime(time);
entity.setCreateDate(DateTime.now().toDate());
entity.setUsername("zhengzizhi@126.com");
entity.setIp("192.168.10.10");
sysLogMapper.insertSelective(entity);
}
}
package com.contoso.controller;
import javax.annotation.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.contoso.annotation.LogAnnotation;
import com.contoso.dao.SysUserMapper;
import com.contoso.domain.SysUser;
import com.contoso.dto.LogUpdateDto;
import com.contoso.enums.StatusCode;
import com.contoso.response.BaseResponse;
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private SysUserMapper userMapper;
@LogAnnotation("面向切面编程的-日志操作")
@RequestMapping(value = "update", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE })
public BaseResponse<SysUser> update(@RequestBody LogUpdateDto dto) throws Exception {
BaseResponse<SysUser> response = new BaseResponse<SysUser>(StatusCode.Success);
SysUser user = new SysUser();
user.setId(2);//模拟id=2的用户修改自己的姓名
user.setName(dto.getName());//姓名
user.setCode(dto.getCode());//验证码
userMapper.updateByPrimaryKeySelective(user);
response.setData(user);
response.setCode(200);
return response;
}
}
package com.contoso.dto;
import java.io.Serializable;
public class LogUpdateDto implements Serializable {
private static final long serialVersionUID = 1297735262193418898L;
private String name;
private String code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
package com.contoso.enums;
public enum StatusCode {
Success(0,"成功"),
Fail(-1,"失败"),
InvalidParams(201,"非法的参数!"),
InvalidGrantType(202,"非法的授权类型");
private Integer code;
private String msg;
StatusCode(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.contoso.response;
import com.contoso.enums.StatusCode;
public class BaseResponse<T> {
private Integer code; //状态码code
private String msg; //状态码对应的描述信息msg
private T data; //响应数据
public BaseResponse(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public BaseResponse(StatusCode statusCode) {
this.code = statusCode.getCode();
this.msg = statusCode.getMsg();
}
public BaseResponse(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
启动项目控制台会打印如下信息,出错的原因是自动生成的2个接口文件 ,都没有手动添加@Mapper注解
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
[32m :: Spring Boot :: [39m [2m (v2.2.1.RELEASE)[0;39m
[2m2019-11-19 11:24:12.455[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mcom.contoso.Application [0;39m [2m:[0;39m Starting Application on contoso.com with PID 23512 (/home/myth/coding/spring-boot-aop-example2/target/classes started by myth in /home/myth/coding/spring-boot-aop-example2)
[2m2019-11-19 11:24:12.459[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mcom.contoso.Application [0;39m [2m:[0;39m No active profile set, falling back to default profiles: default
[2m2019-11-19 11:24:13.103[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Bootstrapping Spring Data repositories in DEFAULT mode.
[2m2019-11-19 11:24:13.115[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Finished Spring Data repository scanning in 8ms. Found 0 repository interfaces.
[2m2019-11-19 11:24:13.195[0;39m [33m WARN[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.m.s.mapper.ClassPathMapperScanner [0;39m [2m:[0;39m No MyBatis mapper was found in '[com.contoso]' package. Please check your configuration.
[2m2019-11-19 11:24:13.382[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2m2019-11-19 11:24:13.707[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat initialized with port(s): 8080 (http)
[2m2019-11-19 11:24:13.714[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.apache.catalina.core.StandardService [0;39m [2m:[0;39m Starting service [Tomcat]
[2m2019-11-19 11:24:13.715[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36morg.apache.catalina.core.StandardEngine [0;39m [2m:[0;39m Starting Servlet engine: [Apache Tomcat/9.0.27]
[2m2019-11-19 11:24:13.777[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.a.c.c.C.[Tomcat].[localhost].[/] [0;39m [2m:[0;39m Initializing Spring embedded WebApplicationContext
[2m2019-11-19 11:24:13.778[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.web.context.ContextLoader [0;39m [2m:[0;39m Root WebApplicationContext: initialization completed in 1275 ms
[2m2019-11-19 11:24:13.844[0;39m [33m WARN[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mConfigServletWebServerApplicationContext[0;39m [2m:[0;39m Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'logAspect': Unsatisfied dependency expressed through field 'sysLogMapper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.contoso.dao.SysLogMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
[2m2019-11-19 11:24:13.848[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.apache.catalina.core.StandardService [0;39m [2m:[0;39m Stopping service [Tomcat]
[2m2019-11-19 11:24:13.879[0;39m [32m INFO[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mConditionEvaluationReportLoggingListener[0;39m [2m:[0;39m
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
[2m2019-11-19 11:24:13.974[0;39m [31mERROR[0;39m [35m23512[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.b.d.LoggingFailureAnalysisReporter [0;39m [2m:[0;39m
***************************
APPLICATION FAILED TO START
***************************
Description:
Field sysLogMapper in com.contoso.aspect.LogAspect required a bean of type 'com.contoso.dao.SysLogMapper' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.contoso.dao.SysLogMapper' in your configuration.
正确的添加了@Mapper注解的接口文件代码如下:
package com.contoso.dao;
import org.apache.ibatis.annotations.Mapper;
import com.contoso.domain.SysLog;
@Mapper
public interface SysLogMapper {
int deleteByPrimaryKey(Long id);
int insert(SysLog record);
int insertSelective(SysLog record);
SysLog selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(SysLog record);
int updateByPrimaryKey(SysLog record);
}
package com.contoso.dao;
import org.apache.ibatis.annotations.Mapper;
import com.contoso.domain.SysUser;
@Mapper
public interface SysUserMapper {
int deleteByPrimaryKey(Integer id);
int insert(SysUser record);
int insertSelective(SysUser record);
SysUser selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(SysUser record);
int updateByPrimaryKey(SysUser record);
}
重新启动项目成功后控制台会打印如下信息:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
[32m :: Spring Boot :: [39m [2m (v2.2.1.RELEASE)[0;39m
[2m2019-11-19 16:59:42.720[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mcom.contoso.Application [0;39m [2m:[0;39m Starting Application on contoso.com with PID 30057 (/home/myth/coding/spring-boot-aop-example2/target/classes started by myth in /home/myth/coding/spring-boot-aop-example2)
[2m2019-11-19 16:59:42.724[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mcom.contoso.Application [0;39m [2m:[0;39m No active profile set, falling back to default profiles: default
[2m2019-11-19 16:59:43.549[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Bootstrapping Spring Data repositories in DEFAULT mode.
[2m2019-11-19 16:59:43.563[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36m.s.d.r.c.RepositoryConfigurationDelegate[0;39m [2m:[0;39m Finished Spring Data repository scanning in 10ms. Found 0 repository interfaces.
[2m2019-11-19 16:59:43.949[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mtrationDelegate$BeanPostProcessorChecker[0;39m [2m:[0;39m Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2m2019-11-19 16:59:44.324[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat initialized with port(s): 8080 (http)
[2m2019-11-19 16:59:44.330[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.apache.catalina.core.StandardService [0;39m [2m:[0;39m Starting service [Tomcat]
[2m2019-11-19 16:59:44.330[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36morg.apache.catalina.core.StandardEngine [0;39m [2m:[0;39m Starting Servlet engine: [Apache Tomcat/9.0.27]
[2m2019-11-19 16:59:44.392[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.a.c.c.C.[Tomcat].[localhost].[/] [0;39m [2m:[0;39m Initializing Spring embedded WebApplicationContext
[2m2019-11-19 16:59:44.392[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.web.context.ContextLoader [0;39m [2m:[0;39m Root WebApplicationContext: initialization completed in 1627 ms
[2m2019-11-19 16:59:45.355[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.s.concurrent.ThreadPoolTaskExecutor [0;39m [2m:[0;39m Initializing ExecutorService 'applicationTaskExecutor'
[2m2019-11-19 16:59:45.768[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat started on port(s): 8080 (http) with context path ''
[2m2019-11-19 16:59:45.772[0;39m [32m INFO[0;39m [35m30057[0;39m [2m---[0;39m [2m[ main][0;39m [36mcom.contoso.Application [0;39m [2m:[0;39m Started Application in 3.404 seconds (JVM running for 3.944)
[myth@contoso ~]$ mysql -uroot -pdbpass -h127.0.0.1 -e"select * from testdb.sys_log"
+----+--------------------+------------------------------------+------------------------------------------------+---------------------------------------+------+---------------+---------------------+
| id | username | operation | method | params | time | ip | create_date |
+----+--------------------+------------------------------------+------------------------------------------------+---------------------------------------+------+---------------+---------------------+
| 9 | zhengzizhi@126.com | 面向切面编程的-日志操作 | com.contoso.controller.UserController.update() | {"name":"jack@163.com","code":"2528"} | 234 | 192.168.10.10 | 2019-11-19 03:39:03 |
+----+--------------------+------------------------------------+------------------------------------------------+---------------------------------------+------+---------------+---------------------+
[myth@contoso ~]$