一文彻底帮你打通 SpringAOP 的任督二脉,大厂高薪指日可待,建议收藏!!!
我们通过日志的案例来给大家来介绍,先看下我们不使用 AOP 的情况下来实现日志记录方法执行的时间。
1.1 非 AOP 实现
首先创建一个 SpringBoot 项目,然后创建 IUserService 接口,定义如下:
public interface IUserService {
pu
blic void log1();
public void log2();
}
然后创建接口的实现,如下:
@Service
public class UserServiceImpl implements IUserService {
@Override
public void log1() {
long start = System.currentTimeMillis();
try {
Thread.sleep(5);
System.out.println("log1 方法执行了 ...");
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("log1 方法执行耗时:" + (end - start));
}
@Override
public void log2() {
try {
Thread.sleep(5);
System.out.println("log2 方法执行了 ...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试代码
//@SpringBootApplication
@Configuration
@ComponentScan
public class SpringAopDemo02Application {
public static void main(String[] args) {
//SpringApplication.run(SpringAopDemo02Application.class, args);
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringAopDemo02Application.class);
IUserService bean = ac.getBean(IUserService.class);
bean.log1();
}
}
![](https://static001.geekbang.org/infoq/6c/6c10447b484d40eb1e06033d2d3f173f.png)
到这儿我们可以看出在 Service 中我们的核心业务代码和日志模块的代理耦合在了一块,这显然是不合适的,这时 AOP 就派上用场了。
1.2 AOP 实现
Spring 中的 AOP 的实现有多种方式,本文就不具体的来一一介绍了,感兴趣的可以参考本人的另一篇文章
https://blog.csdn.net/qq_38526573/article/details/86441916
本文重点介绍原理,我们需要先添加 AspectJ 的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
然后定义切面类
@Aspect
@Component
public class MyAspect {
/**
定义一个环绕通知
@param pjp
@return
*/
@Around("execution(* com.bobo.service.impl.*.log2(..))")
public Object around(ProceedingJoinPoint pjp){
long start = System.currentTimeMillis();
Object proceed = null;
try {
// 执行目标对象的方法
proceed = pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println(pjp.getSignature().getName() + " 执行耗时:" + (end - start));
return proceed;
}
}
然后我们在需要添加@EnableAspectJAutoProxy
注解来放开代理的使用
//@SpringBootApplication
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class SpringAopDemo02Application {
public static void main(String[] args) {
//SpringApplication.run(SpringAopDemo02Application.class, args);
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringAopDemo02Application.class);
IUserService bean = ac.getBean(IUserService.class);
bean.log1();
System.out.println("-------------------");
bean.log2();
}
}
通过输入我们发现代理生效了
![](https://static001.geekbang.org/infoq/27/2738b9c7cf80cc355bf56ecc00a02684.png)
通过上面的操作你会发现 SpringAOP 的实现还是比较简单的,也实现了业务代码和系统功能的分离。更利于系统的扩展。
上面的案例实现了 AOP,接下来我们需要分析下 AOP 的原理,前面介绍了代理模式,我们知道代理模式的实现方式有多种,首先我们来看看 AOP 是采用的 JDK 代理还是 CGLIB 代理呢?
2.1 AOP 的本质
其实在 Spring 的 AOP 中既有 JDK 代理的实现也有 CGLIB 的使用,为什么这么说呢?我们通过演示带大家看看。首先在前面的测试案例的基础上我们通过 debug 模式来看
![](https://static001.geekbang.org/infoq/46/460acfe27975fe06f058ea5797820168.png)
通过断点我们发现 IUserService 的 bean 对象是一个 JDK 动态代理的对象。那 CGLIB 代理呢?我们这样来做。定义一个 PersonServiceImpl 这个 Service 没有实现任何的接口
@Service
public class PersonServiceImpl {
public void show(){
System.out.println("Hello ...");
}
}
评论