SpringBoot AOP
目录
- SpringBoot AOP
- 写法一: @Before("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))")
- 一、AOP开发
- 1.1 概述
- 1.2使用方法
- 1.3创建项目并添加maven依赖
- 1.4 创建Javabean测试类
- 1.5 创建切面
- 1.6 测试类
- 1.7 测试结果
- 1.8 结论
- 1.9 代理方式的切换
- 1.9.1 设计一个接口ManInterface
- 1.9.2 javaBean目标类Man实现ManInterface接口
- 1.9.3 修改application.yml文件的切换方式代理方式
- 1.9.4 测试类
- 1.9.5 测试结果
- 写法二:
- public static final String POINT_CUT = "execution(* com.bjpowernode.springboot03aop.domain.Man.*(..))";
- @Before(value=POINT_CUT)
- 二、AOP开发
- 2.1 pom.xml
- 2.2 javabean
- 2.3 切面类(不一样的地方)
- 2.4 测试类
- 2.5 测试结果
- 写法三:
- 三、AOP开发
- 3.1 pom.xml
- 3.2 javabean
- 3.3 切面类(不一样的地方)
- 3.4 测试类
- 3.5 测试结果
写法一: @Before(“execution(* com.bjpowernode.springboot07.javabean.Man.eat(…))”)
一、AOP开发
1.1 概述
aop是spring的两大功能模块之一,功能非常强大,为解耦提供了非常优秀的解决方案。SpringBoot集成aop是非常方便的,下面使用aop来拦截业务组件的方法
Aop的作用:在不修改源代码的情况下,对类里面的方法进行增强(前置,后置,环绕,异常)
Aop的关键点:
切入点: 被增强的方法
通知/增强: 就是具体增强的代码
1.2使用方法
使用springboot操作aop 与 直接使用spring的注解方式操作aop方式是一致的
1.3创建项目并添加maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1.4 创建Javabean测试类
javabean
Man.java
package com.bjpowernode.springboot07.javabean;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class Man {
public void eat(String foodName){
System.out.println(foodName+"真好吃");
}
}
1.5 创建切面
package com.bjpowernode.springboot07.aop;
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.springframework.stereotype.Component;
@Component
@Aspect
public class ManAspect {
@Before("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))")
public void beforeAdvice(){
System.out.println("ManAspect.beforeAdvice");
}
@After("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))")
public void afterAdvice(){
System.out.println("ManAspect.afterAdvice");
}
@Around("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("ManAspect.aroundAdvice--start");
proceedingJoinPoint.proceed();
System.out.println("ManAspect.aroundAdvice--end");
}
}
1.6 测试类
package com.bjpowernode.springboot07;
import com.bjpowernode.springboot07.javabean.Man;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot07ApplicationTests {
@Autowired
private Man man;
@Test
public void testAop(){
System.out.println(man.getClass().getName());
man.eat("油条");
}
}
1.7 测试结果
1.8 结论
springboot aop 默认的动态代理方式为cglib
SpringBoot 2.x开始,AOP为了解决使用JDK动态代理可能导致的类型转换异常,而使用CGLIB。
1.9 代理方式的切换
使用JDK动态代理的方式
1.9.1 设计一个接口ManInterface
package com.bjpowernode.springboot07.javabean;
public interface ManInterface {
void eat(String foodName);
}
1.9.2 javaBean目标类Man实现ManInterface接口
package com.bjpowernode.springboot07.javabean;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class Man implements ManInterface{
public void eat(String foodName){
System.out.println(foodName+"真好吃");
}
}
从springBoot2.x以后,切换代理方式需要在配置文件中配置,使用注解切换的方式失效了
1.9.3 修改application.yml文件的切换方式代理方式
spring:
aop:
proxy-target-class: false # false表示使用JDK代理 true表示使用CGLIB代理,SpringBoot2.x以后默认使用CGLIB代理
1.9.4 测试类
需要改为注入接口
package com.bjpowernode.springboot07;
import com.bjpowernode.springboot07.javabean.Man;
import com.bjpowernode.springboot07.javabean.ManInterface;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot07ApplicationTests {
@Autowired
private ManInterface man;
@Test
public void testAop(){
System.out.println(man.getClass().getName());
man.eat("油条");
}
}
1.9.5 测试结果
写法二:
public static final String POINT_CUT = “execution(* com.bjpowernode.springboot03aop.domain.Man.*(…))”;
@Before(value=POINT_CUT)
二、AOP开发
2.1 pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.2 javabean
Man.java
package com.bjpowernode.springboot03aop.domain;
import org.springframework.stereotype.Component;
/*
*将此类加入IOC管理
* AOP作用的类一定要加入IOC容器中
*/
@Component
public class Man {
/**
* 吃饭的方法
* @param foodName
* @return
*/
public String eat(String foodName){
System.out.println("吃"+foodName);
int i=1/0;
return foodName+"很好吃";
}
}
2.3 切面类(不一样的地方)
package com.bjpowernode.springboot03aop.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/*
*切面类加入IOC容器管理
* 添加切面的标识
*/
@Aspect
@Component
public class ManAspect {
/*
*切入点
*/
public static final String POINT_CUT = "execution(* com.bjpowernode.springboot03aop.domain.Man.*(..))";
/*
* 前置通知
*/
@Before(value=POINT_CUT)
public void before(){
System.out.println("吃饭前洗手");
}
/*
* 后置通知
*/
@After(POINT_CUT)
public void after(){
System.out.println("饭后甜点");
}
/**
* 环绕通知
* @param proceedingJoinPoint
* @return
*/
@Around(value = POINT_CUT)
public Object around(ProceedingJoinPoint proceedingJoinPoint){
Object result = null;
try {
System.out.println("执行目标方法之前");
//执行目标方法
result = proceedingJoinPoint.proceed();
System.out.println("执行目标方法之后");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}
/**
* 异常通知
* @param ex
*/
@AfterThrowing(value = POINT_CUT,throwing = "ex")
public void afterThrowing(Throwable ex){
System.out.println("异常了"+ex.getMessage());
}
}
2.4 测试类
package com.bjpowernode.springboot03aop;
import com.bjpowernode.springboot03aop.domain.Man;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot03AopApplicationTests {
@Autowired
private Man man;
@Test
void contextLoads() {
System.out.println(man.getClass().getName());
man.eat("面条");
}
}
2.5 测试结果
写法三:
三、AOP开发
3.1 pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3.2 javabean
Man.java
package com.bjpowernode.springboot03aop.domain;
import org.springframework.stereotype.Component;
/*
*将此类加入IOC管理
* AOP作用的类一定要加入IOC容器中
*/
@Component
public class Man {
/**
* 吃饭的方法
* @param foodName
* @return
*/
public String eat(String foodName){
System.out.println("吃"+foodName);
int i=1/0;
return foodName+"很好吃";
}
}
3.3 切面类(不一样的地方)
package com.bjpowernode.springboot03aop2.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/*
*切面类加入IOC容器管理
* 添加切面的标识
*/
@Aspect
@Component
public class ManAspect {
@Pointcut("execution(* com.bjpowernode.springboot03aop2.domain.Man.*(..))")
public void pointCutMethod(){
}
/*
* 前置通知
*/
@Before("pointCutMethod()")
public void before(){
System.out.println("吃饭前洗手");
}
/*
* 后置通知
*/
@After("pointCutMethod()")
public void after(){
System.out.println("饭后甜点");
}
/**
* 环绕通知
* @param proceedingJoinPoint
* @return
*/
@Around("pointCutMethod()")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
Object result = null;
try {
System.out.println("执行目标方法之前");
//执行目标方法
result = proceedingJoinPoint.proceed();
System.out.println("执行目标方法之后");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}
/**
* 异常通知
* @param ex
*/
@AfterThrowing(value = "pointCutMethod()",throwing = "ex")
public void afterThrowing(Throwable ex){
System.out.println("异常了"+ex.getMessage());
}
}
3.4 测试类
package com.bjpowernode.springboot03aop;
import com.bjpowernode.springboot03aop.domain.Man;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot03AopApplicationTests {
@Autowired
private Man man;
@Test
void contextLoads() {
System.out.println(man.getClass().getName());
man.eat("面条");
}
}