共计 5405 个字符,预计需要花费 14 分钟才能阅读完成。
一、成果演示
以上面的例子演示,
业务类,
UserService.java
package com.my.template.service;
import com.my.template.entity.User;
import org.springframework.stereotype.Service;
/**
* @date 2022/8/9 15:28
*/
@Service
public class UserService implements Us{
@Override
public void saveUser(User user){System.out.println("保留 user 对象到数据库:"+user);
}
}
切面类,
LogAspect.java
package com.my.template.aop;
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.springframework.stereotype.Component;
/**
* @date 2022/8/11 14:12
*/
@Component
@Aspect
public class LogAspect {@Pointcut("execution(* com.my.template.service.UserService.*(..))")
public void pointCut(){}
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint){System.out.println("办法执行前 -20220816");
}
@AfterReturning(value = "pointCut()")
public void after(JoinPoint joinPoint){System.out.println("办法执行后 -20220816");
}
}
测试的 controller
UserController.java
package com.my.template.controller;
import com.my.template.entity.User;
import com.my.template.service.Us;
import com.my.template.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @date 2022/8/9 15:35
*/
@RestController
public class UserController {
@Autowired
private Us us;
@RequestMapping("/saveUser")
public String saveUser(){User user=new User();
user.setId("1");
user.setName("张三");
us.saveUser(user);
return "success";
}
}
sprinboot 的启动类,
BootServer.java
package com.my.template;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.ImportResource;
/**
* 启动类
* @date 2022/6/3 21:32
*/
@SpringBootApplication()
public class BootServer {public static void main(String[] args) {
try {SpringApplication.run(BootServer.class);
}catch (Exception e){e.printStackTrace();
}
}
}
测试后果如下,
2022-08-16 22:30:44.082 INFO 25716 --- [nio-9099-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 6 ms
办法执行前 -20220816
保留 user 对象到数据库:User{name='张三', id='1'}
办法执行后 -20220816
从下面的测试后果来看,没有加 @EnableAspectJAutoProxy 注解,然而 AOP 失效了,这是为什么?
二、为什么不加 @EnableAspectJAutoProxy 切面失效
对于这个问题我排查了很久,最初在依赖中找到了起因,看下 pom 文件
pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springTemplate</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--spring-boot 的 web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<!-- 自定义的 starter-->
<dependency>
<groupId>org.example</groupId>
<artifactId>customer-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 应用 springAOP 须要引入该依赖 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
在依赖中有 spring-boot-starter-web 的依赖,该依赖有上面的依赖,
会引入 spring-boot-autoconfigure 的依赖,这是主动拆卸的依赖,也就是会读取其下的 spring.factories 文件,在该文件中有上面的配置,
没错就是因为 AopAutoConfiguration 类的问题。上面看具体起因。
三、起因剖析
要看具体起因,咱们就要关上 AopAutoConfiguration 这个类看下,
先看正文吧,正文中说 AopAutoConfiguration 等同于 @EnableAspectJAutoProxy 注解,也就是该类起的作用和 @EnableAspectJAutoProxy 是一样的,再看该类上的注解,重点看 @ConditionalOProperty 注解中的内容,意思是如果 在配置文件中有”spring.aop.auto“的配置,如果不配置为 true,否则能够配置为 false,当初我的配置文件中是没有该配置项的,
server.port=9099
spring.datasource.type=com.mysql.cj.jdbc.MysqlDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource..driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=yh_dev
spring.datasource..password=DvpJe2x
spring.datasource.url=jdbc:mysql://10.0.0.37:3306/channel_center
#?????
my.customer.name=hello
my.customer.code=autoconfiguration
那么我当初减少该配置,并设置为 false,
server.port=9099
spring.datasource.type=com.mysql.cj.jdbc.MysqlDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource..driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=yh_dev
spring.datasource..password=DvpJe2x
spring.datasource.url=jdbc:mysql://10.0.0.37:3306/channel_center
#?????
my.customer.name=hello
my.customer.code=autoconfiguration
spring.aop.auto=false
重启服务之后,看测试后果,
从测试后果能够看到 springAOP 没有起作用,当初在启动类上加上 @EnableAspectJAutoProxy 注解,看下测试后果,
从下面的测试后果能够看到,增加了 @EnableAspectJAutoProxy 注解 springAOP 失效了。
综上,在 springboot 环境下,因为存在 spring-boot-autoconfigure 依赖,默认会注入 AopAutoConfiguration 配置类,该类的作用等同于 @EnableAspectJAutoProxy 注解,所以在这种状况下能够不加 @EnableAspectJAutoProxy 注解,AopAutoConfiguration 能够通过 spring.aop.auto 属性管制;
四、总结
本文次要剖析了在 springboot 环境下,不加 @EnableAspectJAutoProxy 注解 springAOP 依然失效的问题。 为了保险期间请一律加上 @EnableAspetJAutoProxy 注解。
- AopAutoConfiguration 类等同于 @EnableAspectJAutoProxy 注解;
- spring.aop.auto=ture/false 属性能够管制 AopAutoConfiguration 类是否失效;
欢送关注我的公众号:敲代码的老贾,回复“支付”赠送《Java 面试》材料,阿里,腾讯,字节,美团,饿了么等大厂