spring boot AOP练习 @Aspect
程序员文章站
2022-06-16 16:09:18
spring boot AOP练习 @Aspect环境 org.springframework.boot spring-boot-starter-aop ...
spring boot AOP练习 @Aspect
环境
<!-- 主要依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
开启配置
/**
* @author smxr
* @date 2020/11/19
* @time 11:11
* @EnableAspectJAutoProxy(proxyTargetClass = true)
* 这个为true时,则会使用 cglib 的动态代理方式;缺点:拓展类的实例用final修饰时,则无法进行织入
* 默认使用的是jdk动态代理; 缺点:会有一点影响性能
*/
@Configuration
@EnableAspectJAutoProxy
public class ConfigBean {
@Conditional(UserConditional.class)
@Bean
public User user(){
System.out.println("张三加载中...........");
User user = new User();
user.setUserName("张三");
return user;
}
@Conditional(UserConditional2.class)
@Bean
public User user2(){
System.out.println("李四加载中...........");
User user = new User();
user.setUserName("李四");
return user;
}
}
项目结构
@Aspect 切面类
/**
* @author smxr
* @date 2020/11/23
* @time 10:33
*/
@Aspect
@Component
public class AspectUserService {
// @Pointcut("execution( public * com.redis.service.impl.UserServiceImpl.sleep(..))")
private void PointCut(){}
@Before("execution(public * com.redis.service.UserService.sleep(..))")
public void sleepBefore(JoinPoint joinPoint){
// System.out.println(joinPoint.toString());//输出结果:execution(void com.redis.service.impl.UserServiceImpl.sleep())
System.out.println("前置拦截开始了");//2
}
@After("execution(public * com.redis.service.UserService.sleep(..))")
public void sleepAfter(JoinPoint joinPoint){
System.out.println("后置拦截开始了");//4
}
@AfterReturning("execution(public * com.redis.service.UserService.sleep(..))")
public void sleepAfterReturning(JoinPoint joinPoint){
System.out.println("完成拦截开始了");//3
}
@AfterThrowing("execution(public * com.redis.service.UserService.sleep(..))")
public void sleep(JoinPoint joinPoint){
System.out.println("异常拦截开始了");
}
@Around("execution(public * com.redis.service.UserService.sleep(..))")
public void sleepAround(ProceedingJoinPoint proceedingJoinPoint){
try {
System.out.println("前置环绕:运行......");//1
proceedingJoinPoint.proceed();
System.out.println("后置环绕:运行......");//5
} catch (Throwable throwable) {
System.out.println("环绕:运行异常......");
}
}
}
相关接口和实现类
/**
* @author smxr
* @date 2020/11/23
* @time 10:20
*/
public interface UserService {
public void eat();
public void sleep();
public void corporate_slave();
public void speak(User user);
}
import com.redis.pojo.User;
import com.redis.service.UserService;
import org.springframework.stereotype.Service;
/**
* @author smxr
* @date 2020/11/23
* @time 10:25
*/
@Service
public class UserServiceImpl implements UserService {
@Override
public void eat() {
System.out.println("要去吃饭了......");
}
@Override
public void sleep() {
System.out.println("终于到了放松的时候了........");
}
@Override
public void corporate_slave() {
System.out.println("要去工作了.........");
}
@Override
public void speak(User user) {
System.out.println(user.getUserName()+"说:.......");
}
}
测试及结果
@SpringBootTest
class SpringbootRedisApplicationTests {
@Autowired
UserServiceImpl userService;
@Test
void AOPTest(){
userService.sleep();
}
-----------------------------------------------
前置环绕:运行......
前置拦截开始了
终于到了放松的时候了........
完成拦截开始了
后置拦截开始了
后置环绕:运行......
不知道有没有错,反正跑出来的顺序就这样的.
切面有参的AOP练习
AspectUserService.class
//不关注 参数
@Around("execution(public * com.redis.service.UserService.speak(..))")
public void speakAround(ProceedingJoinPoint proceedingJoinPoint){
try {
System.out.println("前置环绕:运行......");
proceedingJoinPoint.proceed();
System.out.println("后置环绕:运行......");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
//
/*
* 关注 参数
* && args(user) 指定参数;要传入的参数
* && bean(userServiceImpl) 指定要使用的容器组件名;即这个指定的(userServiceImpl)组件bean去调用,才能生效.
*/
@Around("execution(public * com.redis.service.UserService.speak(..)) && args(user)")
public void speakAround(ProceedingJoinPoint proceedingJoinPoint,User user){
try {
if (user.getUserAge()==69){
System.out.println(user.getUserAge()+"老同志即将发言,请注意听讲!如果你大意了,就没有闪了");
}else if (user.getUserAge()>69){
System.out.println(user.getUserAge()+"老同志即将发言,请注意听讲!");
}else {
System.out.println(user.getUserName()+"的前置环绕即将说话:请注意听讲");
}
proceedingJoinPoint.proceed();
if (user.getUserAge()==69){
System.out.println(user.getUserAge()+"老同志发言完成,恭喜大家获取技能闪电五连变");
}else {
System.out.println(user.getUserName()+"的后置环绕完成!");
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
测试代码
@Test
void AOPTest1(){
User user3 = new User();
user3.setUserName("马老师");
user3.setUserAge(69);
userService.speak(user3);
System.out.println("----------------分界线--------------------");
User user4 = new User();
user4.setUserName("老马");
user4.setUserAge(80);
userService.speak(user4);
}
前置环绕:运行......
69老同志即将发言,请注意听讲!如果你大意了,就没有闪了
马老师说:.......
69老同志发言完成,恭喜大家获取技能闪电五连变
后置环绕:运行......
----------------分界线--------------------
前置环绕:运行......
80老同志即将发言,请注意听讲!
老马说:.......
老马的后置环绕完成!
后置环绕:运行......
//要注意指定的 && bean(userServiceImpl) 否则重新注入一个新的userServiceImpl2 是不能调用的
@Autowired
UserServiceImpl userService;
还是看下案例吧!
新注入一个userService2
@Configuration
@EnableAspectJAutoProxy
public class ConfigBean {
@Conditional(UserConditional.class)
@Bean
public User user(){
System.out.println("张三加载中...........");
User user = new User();
user.setUserName("张三");
return user;
}
@Conditional(UserConditional2.class)
@Bean
public User user2(){
System.out.println("李四加载中...........");
User user = new User();
user.setUserName("李四");
return user;
}
@Bean
public UserServiceImpl userService2(){
UserServiceImpl userService2 = new UserServiceImpl();
return userService2;
}
}
原来的service 声明bean名字
/**
* @author smxr
* @date 2020/11/23
* @time 10:25
*/
@Service(value = "userService")
public class UserServiceImpl implements UserService {
@Override
public void eat() {
System.out.println("要去吃饭了......");
}
@Override
public void sleep() {
System.out.println("终于到了放松的时候了........");
}
@Override
public void corporate_slave() {
System.out.println("要去工作了.........");
}
@Override
public void speak(User user) {
System.out.println(user.getUserName()+"说:.......");
}
}
测试及结果
@SpringBootTest
class SpringbootRedisApplicationTests {
@Autowired
UserServiceImpl userService;
@Autowired
UserServiceImpl userService2;
@Test
void AOPTest1(){
User user3 = new User();
user3.setUserName("马老师");
user3.setUserAge(69);
userService.speak(user3);
System.out.println("----------------分界线--------------------");
User user4 = new User();
user4.setUserName("老马");
user4.setUserAge(80);
userService2.speak(user4);
}
}
69老同志即将发言,请注意听讲!如果你大意了,就没有闪了
马老师说:.......
69老同志发言完成,恭喜大家获取技能闪电五连变
----------------分界线--------------------
老马说:.......
上面的我把 无参的那个给注释掉了, 下面解开注释在跑一次
//不关注 参数
@Around("execution(public * com.redis.service.UserService.speak(..))")
public void speakAround(ProceedingJoinPoint proceedingJoinPoint){
try {
System.out.println("前置环绕:运行......");
proceedingJoinPoint.proceed();
System.out.println("后置环绕:运行......");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
//
/*
* 关注 参数
* && args(user) 指定参数;要传入的参数
* && bean(userServiceImpl) 指定要使用的容器组件名;即这个指定的(userServiceImpl)组件bean去调用,才能生效.
*/
@Around("execution(public * com.redis.service.UserService.speak(..)) && args(user)&& bean(userService)")
public void speakAround(ProceedingJoinPoint proceedingJoinPoint,User user){
try {
if (user.getUserAge()==69){
System.out.println(user.getUserAge()+"老同志即将发言,请注意听讲!如果你大意了,就没有闪了");
}else if (user.getUserAge()>69){
System.out.println(user.getUserAge()+"老同志即将发言,请注意听讲!");
}else {
System.out.println(user.getUserName()+"的前置环绕即将说话:请注意听讲");
}
proceedingJoinPoint.proceed();
if (user.getUserAge()==69){
System.out.println(user.getUserAge()+"老同志发言完成,恭喜大家获取技能闪电五连变");
}else {
System.out.println(user.getUserName()+"的后置环绕完成!");
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
测试和结果
69老同志即将发言,请注意听讲!如果你大意了,就没有闪了
前置环绕:运行......
马老师说:.......
后置环绕:运行......
69老同志发言完成,恭喜大家获取技能闪电五连变
----------------分界线--------------------
前置环绕:运行......
老马说:.......
后置环绕:运行......
看代码来说如果指定了参数和指定了运行的bean ,那么这个切面只有相应的bean才能被调用
如果只指定了参数和无视参数,指定了参数的优先级高.
本文地址:https://blog.csdn.net/qq_44738044/article/details/109994857
推荐阅读
-
spring boot 使用Aop通知打印控制器请求报文和返回报文问题
-
spring boot aop 记录方法执行时间代码示例
-
Spring Boot配置AOP打印日志的全过程
-
spring boot 使用Aop通知打印控制器请求报文和返回报文问题
-
Spring Boot使用AOP防止重复提交的方法示例
-
spring boot aop 记录方法执行时间代码示例
-
Spring Boot 入门(五):集成 AOP 进行日志管理
-
SpringBoot 源码解析 (十)----- Spring Boot 精髓:集成AOP
-
荐 微服务之Spring Boot2—降低开发复杂度之面向切面AOP
-
spring源码---Aop:解析@Aspect